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

286 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
- Встраиваемый расширяемый не имеющий средств ввода-вывода ЯП
- 5 примитивных типов данных - Number, String, Boolean, Null, Undefined
- Объектный тип данных - Object
- 15 различных видов инструкций
> [!warning] Дальнейшие примеры будут до стандарта ES6, то есть не совсем актуальные, использование `var` - моветон в наше время. Также после 2020 года уже 7 примитивов - еще Symbol и BigInt
## Особенности языка
- Блок не ограничивает область видимости переменной:
```JavaScript
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();
```
- Если переменная объявлена вне функции, то она в глобальной области видимости
```JavaScript
var a = 42;
function foo() {
alert(a);
}
foo();
```
> [!hint] `alert()` вызывает всплывающее окно, синхронный и блокирующий метод - блокирует Event Loop
- Функция - это тоже объект
```JavaScript
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` - константа
## Форматирование вывода
```JavaScript
const first = 'Adrian';
const last = 'Mejia';
console.log(`Your name is ${first} ${last}.`);
```
> [!hint] Нужны косые кавычки ``
## Деструктуризация
- Особый синтаксис присваивания, при котором можно присвоить массив или объект сразу нескольким переменным, разбив его на части
```JavaScript
const array = [1, 2, 3, 4];
const [first, ,third] = array;
console.log(first, third); // 1 3
```
- Обмен значениями
```JavaScript
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
```
- Сопоставление параметров
```JavaScript
const user = {firstName: 'Adrian', lastName: 'Mejia'};
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
console.log(getFullName(user)); // Adrian Mejia
```
> [!hint] { } - создание объекта, аналог хэш-мапы
- Деструктуризация объекта
```JavaScript
function settings() {
return { display: { color: 'red' }, keyboard: { layout: 'querty' } };
}
const { display: { color: displayColor }, keyboard: { layout: keyboardLayout }} = settings();
console.log(displayColor, keyboardLayout); // red querty
```
> [!hint] {} до знака равно - распаковка объектов, а не их создание
## Классы и объекты
```JavaScript
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.
```
## Наследование
```JavaScript
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`
## Приведение типов
Существует два оператора равенства: `==` и `===`
#### Строгое равенство `===`
- Проверяет и тип, и значение
- Никаких скрытых преобразований
```JavaScript
5 === 5 // true
5 === "5" // false
0 === "false" // false
null === undefined // false
```
#### Нестрогое равенство `==`
- Оператор с неявным приведением типов. Если типы разные, движок пытается привести их к одному (чаще всего к числу) по алгоритму
##### Правила кастов
1. Каста `null` и `undefined` - они равны друг другу, но больше не равны ничему в языке
```JavaScript
null == undefined // true
null == 0 // false
```
2. Булеан -> Число (в 0 или 1)
3. Строка -> Число (`"5" -> 5`, `"" -> 0`, `"hello" -> NaN`)
4. Объект -> Примитив (через метод `.toString`)
## Стрелочные функции
```JavaScript
$('.btn').click((event) => this.sendData());
```
## Цикл с итератором
```JavaScript
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);
}
```
## Параметры по умолчанию
```JavaScript
function point(x=0, y=-1, isFlag=true) {
...
}
```
## Rest-параметры
Типо `vararg` в джаве
```JavaScript
function printf(format, ...params) {
...
}
```
### Операция spread
```JavaScript
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 в одном потоке
До промисов был ад колбэков
```JavaScript
// Старый ад (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()`
```JavaScript
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');
})
```
Свой промис
```JavaScript
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` функций
```JavaScript
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$ повтор цикла.