Files
obsidian/Веб/Фронтенд/ECMAScript.md
T
roma-dxunvrs 7637cab7a9
deploy / Pull and Restart (push) Successful in 18s
22.09.26
2026-09-22 22:37:41 +03:00

12 KiB
Raw Blame History

  • Встраиваемый расширяемый не имеющий средств ввода-вывода ЯП
  • 5 примитивных типов данных - Number, String, Boolean, Null, Undefined
  • Объектный тип данных - Object
  • 15 различных видов инструкций

[!warning] Дальнейшие примеры будут до стандарта ES6, то есть не совсем актуальные, использование var - моветон в наше время. Также после 2020 года уже 7 примитивов - еще Symbol и BigInt

Особенности языка

  • Блок не ограничивает область видимости переменной:
function foo() {
	var sum = 0;
	for (var i = 0; i < 42; i += 2) {
		var tmp = i+2;
		sum += i*tmp;
	}
	for (var i = 1; i < 42; i += 2) {
		sum += i*i;
	}
	alert(tmp); // вне зоны
	return sum;
}
foo();
  • Если переменная объявлена вне функции, то она в глобальной области видимости
var a = 42;
function foo() {
	alert(a);
}
foo();

[!hint] alert() вызывает всплывающее окно, синхронный и блокирующий метод - блокирует Event Loop

  • Функция - это тоже объект
function sum(a, b) {
	return a+b;
}
var sum2 = function(a, b) {
	return a+b;
}
var sum3 = new Function("a", "b", "return a+b;"); // без комментариев

ES6

  • Новая версия, выпущенная в 2015 году
  • Добавляет новый синтаксис

[!warning] Дальше примеры для ES6 и новее

let и const

Два новых ключевых слова let - переменная с областью видимости в блоке const - константа

Форматирование вывода

const first = 'Adrian';
const last = 'Mejia';
console.log(`Your name is ${first} ${last}.`);

[!hint] Нужны косые кавычки ``

Деструктуризация

  • Особый синтаксис присваивания, при котором можно присвоить массив или объект сразу нескольким переменным, разбив его на части
const array = [1, 2, 3, 4];
const [first, ,third] = array;
console.log(first, third); // 1 3
  • Обмен значениями
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
  • Сопоставление параметров
const user = {firstName: 'Adrian', lastName: 'Mejia'};
function getFullName({ firstName, lastName }) {
	return `${firstName} ${lastName}`;
}
console.log(getFullName(user)); // Adrian Mejia

[!hint] { } - создание объекта, аналог хэш-мапы

  • Деструктуризация объекта
function settings() {
	return { display: { color: 'red' }, keyboard: { layout: 'querty' } };
}

const { display: { color: displayColor }, keyboard: { layout: keyboardLayout }} = settings();

console.log(displayColor, keyboardLayout); // red querty

[!hint] {} до знака равно - распаковка объектов, а не их создание

Классы и объекты

class Animal {
	constructor(name) {
		this.name = name;
	}
	speak() {
		console.log(this.name + ' makes a noise.');
	}
}
const animal = new Animal('animal');
animal.speak(); // animal makes a noise.

Наследование

class Lion extends Animal {
	speak() {
		super.speak();
		console.log(this.name + ' roars.');
	}
}
const lion = new Lion('Simba');
lion.speak();
// Simba makes a noise.
// Simba roars.

Типы данных

Number

  • Любое число под капотом это 64-битное число с плавающей точкой (как double в джаве).
  • Infinity / -Infinity (например при делении на 0)
  • NaN (например при делении строки на число)
  • Опасность сравнения 0.1 + 0.2 === 0.3 // false

String

  • В UTF-16
  • Нет разницы между одинарными и двойными кавычками

Boolean

  • true / false

Undefined

  • undefined
  • Техническое значение по умолчанию
  • Присваивает сам движок

Null

  • null
  • Намеренное отсутствие значения

Symbol

  • Уникальный и неизменяемый идентификатор
  • Symbol("id") === Symbol("id") // false
  • Нужен для создания скрытых свойств внутри объектов, которые нельзя случайно перезаписать или увидеть при обычном переборе через for...in

Object

  • Все, что не примитив
  • Например словари {} - аналог HashMap<String, Object> джавы
  • Массивы, функции, даты, регулярки - все это Object

Приведение типов

Существует два оператора равенства: == и ===

Строгое равенство ===

  • Проверяет и тип, и значение
  • Никаких скрытых преобразований
5 === 5 // true
5 === "5" // false
0 === "false" // false
null === undefined // false

Нестрогое равенство ==

  • Оператор с неявным приведением типов. Если типы разные, движок пытается привести их к одному (чаще всего к числу) по алгоритму
Правила кастов
  1. Каста null и undefined - они равны друг другу, но больше не равны ничему в языке
null == undefined // true
null == 0 // false
  1. Булеан -> Число (в 0 или 1)
  2. Строка -> Число ("5" -> 5, "" -> 0, "hello" -> NaN)
  3. Объект -> Примитив (через метод .toString)

Стрелочные функции

$('.btn').click((event) => this.sendData());

Цикл с итератором

var array = ['a', 'b'];
for (var i = 0; i < array.length; i++) {
	var el = array[i];
	console.log(el);
}
array.forEach(function (el) {
	console.log(el)
});
array.forEach((el) => console.log(el));
for (const el of array) {
	console.log(el);
}

Параметры по умолчанию

function point(x=0, y=-1, isFlag=true) {
	...
}

Rest-параметры

Типо vararg в джаве

function printf(format, ...params) {
	...
}

Операция spread

Math.max(...[2,100,1,6,43]);

const array1 = [1,2,3];
const array2 = ['a', 'b'];
const array3 = [false, true];
console.log([...array1, ...array2, ...array3])

Promise

Это специальный объект, который представляет собой результат асинхронной операции JavaScript - однопоточный, используется Event Loop в одном потоке До промисов был ад колбэков

// Старый ад (Pyramid of Doom):
getUser(userId, function(user) {
    getOrders(user.id, function(orders) {
        getOrderDetails(orders[0].id, function(details) {
            // И так до бесконечности вправо...
        });
    });
});

Состояния промиса

  1. pending (ожидание) - операция запущена, но еще не завершилась
  2. fulfilled (выполнено усешно) - вернул результат
  3. rejected (отклонено с ошибкой) - произошла ошибка

Работа с промисом

.then(), .catch(), .finally()

fetch("https://api.com/user/1") // отправка запроса
	.then(response => response.json())
	.then(user => {
		console.log(user.name);
	})
	.catch(error => { // ошибка на любом этапе
		console.error(error);
	})
	.finally(() => { // выполнится всегда
		console.log('Done');
	})

Свой промис

function printAfterTimeout(string, timeout) {
	return new Promise((resolve, reject) => {
		setTimeout(function(){
			resolve(string);
		}, timeout);
	});
}

printAfterTimeout('Hello', 2e3)
	.then((result) => {
		console.log(result);
		return printAfterTimeout(result + 'Reader', 2e3);
	}).then((result) => {
		console.log(result);
	});

[!hint] В новый промис передается две функции resolve - при успехе и reject - при ошибке

Async и Await

Появились в ES8 (2017 год). Способ писать асинхронный код так, чтобы он читался как синхронный Замена цепочкам .then().catch()

  • async пишется перед объявлением функции. Такая функция автоматически оборачивает то, что возвращает, в Promise
  • Ключевое слово await заставляет функцию поставить выполнение на паузу и дождаться результата
  • await можено использовать только внутри async функций
async function loadUser() {
	try {
		const response = await fetch("https://api.com/...");
		const user = await response.json();
		console.log(user);
	} catch (error) {
		console.error(error)
	}
}

Event Loop и Асинхронность

JavaScript в браузере (и Node.js) — строго однопоточный язык. У него есть только один Call Stack (Стек вызовов), который может выполнять только одну операцию одновременно. Чтобы не блокировать поток тяжелыми задачами (запросы в сеть, таймеры), JS использует механизм Event Loop (Цикл событий) и делегирует работу фоновым C++ потокам браузера (Web APIs).

Приоритет выполнения задач

Движок JS распределяет код и колбэки по трем уровням приоритета:

  1. Стек вызовов (Call Stack) — Абсолютный приоритет Весь текущий синхронный код (циклы for, обычные функции, console.log). Действует правило Run-to-completion: пока стек не опустеет полностью, никакие асинхронные задачи из очередей не начнут выполняться, даже если они уже готовы. Блокировка стека (например, while(true)) намертво вешает весь браузер.
  2. VIP-очередь (Микротаски / Microtasks) — Высокий приоритет Сюда попадают колбэки от Промисов (.then(), catch(), код после await) и MutationObserver. Как только Стек пустеет, Event Loop берет микротаски и выполняет их все до единой, пока эта очередь не станет абсолютно пустой.
  3. Обычная очередь (Макротаски / Macrotasks) — Низкий приоритет Сюда попадают Таймеры (setTimeout, setInterval) и события пользователя (клики click, ввод с клавиатуры). Из этой очереди Event Loop берет строго по ОДНОЙ задаче за один цикл. Выполнив одну макрозадачу, он снова бежит проверять, не появились ли новые микротаски (Промисы), и только потом берет следующую макрозадачу.

[!hint] Кратко: порядок выполнения Синхронный СТЕК \to ВСЕ Микротаски (Промисы) \to ОДНА Макротаска (Таймеры) \to повтор цикла.