12 KiB
- Встраиваемый расширяемый не имеющий средств ввода-вывода ЯП
- 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
Нестрогое равенство ==
- Оператор с неявным приведением типов. Если типы разные, движок пытается привести их к одному (чаще всего к числу) по алгоритму
Правила кастов
- Каста
nullиundefined- они равны друг другу, но больше не равны ничему в языке
null == undefined // true
null == 0 // false
- Булеан -> Число (в 0 или 1)
- Строка -> Число (
"5" -> 5,"" -> 0,"hello" -> NaN) - Объект -> Примитив (через метод
.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) {
// И так до бесконечности вправо...
});
});
});
Состояния промиса
pending(ожидание) - операция запущена, но еще не завершиласьfulfilled(выполнено усешно) - вернул результат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 распределяет код и колбэки по трем уровням приоритета:
- Стек вызовов (Call Stack) — Абсолютный приоритет
Весь текущий синхронный код (циклы
for, обычные функции,console.log). Действует правило Run-to-completion: пока стек не опустеет полностью, никакие асинхронные задачи из очередей не начнут выполняться, даже если они уже готовы. Блокировка стека (например,while(true)) намертво вешает весь браузер. - VIP-очередь (Микротаски / Microtasks) — Высокий приоритет
Сюда попадают колбэки от Промисов (
.then(),catch(), код послеawait) иMutationObserver. Как только Стек пустеет, Event Loop берет микротаски и выполняет их все до единой, пока эта очередь не станет абсолютно пустой. - Обычная очередь (Макротаски / Macrotasks) — Низкий приоритет
Сюда попадают Таймеры (
setTimeout,setInterval) и события пользователя (кликиclick, ввод с клавиатуры). Из этой очереди Event Loop берет строго по ОДНОЙ задаче за один цикл. Выполнив одну макрозадачу, он снова бежит проверять, не появились ли новые микротаски (Промисы), и только потом берет следующую макрозадачу.
[!hint] Кратко: порядок выполнения Синхронный СТЕК
\toВСЕ Микротаски (Промисы)\toОДНА Макротаска (Таймеры)\toповтор цикла.