ES6 як найважливіше оновлення JS
ES6 (ECMAScript 2015) це версія стандарту, ухвалена в червні 2015 року, яка кардинально змінила мову. До неї JavaScript довгі роки не отримував великих оновлень: попередня помітна версія, ES5, вийшла ще у 2009 році. ES6 став тим рубежем, після якого JS перетворився з «мови для браузера» на повноцінну сучасну мову програмування.
Теорія
TL;DR
- ES6 приніс сучасний синтаксис:
letіconst, стрілкові функції, шаблонні рядки, деструктуризацію, spread і rest, класи. - Уперше з'явилися офіційні модулі
import/export, до того їх заміняли IIFE, CommonJS, AMD і RequireJS. Promiseзробив асинхронний код лінійним і став фундаментом дляasync/awaitз ES2017.- Додалися структури даних
Map,Set,WeakMap,WeakSetі методи на кшталтArray.from()таObject.assign(). - З'явилися
Symbol, ітератори й генератори, тобто механіка, на якій тримаютьсяfor...ofі сучасна асинхронність. - Разом це уніфікувало мову для браузера й сервера та відкрило дорогу збирачам, транспіляторам і фреймворкам.
Швидкий приклад
// math.js
export const sum = (a, b) => a + b;
// main.js
import { sum } from './math.js';
const users = [{ name: 'Maria', age: 30 }];
const [{ name, age }] = users;
console.log(`${name} is ${age}, sum = ${sum(2, 3)}`);Новий синтаксис, наближений до сучасних мов
ES6 додав багато конструкцій, які зробили код зрозумілішим, коротшим і безпечнішим.
| Нововведення | Що робить | Приклад |
|---|---|---|
let / const | Блокова область видимості замість var | let x = 10; const y = 20; |
| Стрілкові функції | Компактний синтаксис, лексичний this | arr.map(x => x * 2) |
| Шаблонні рядки | Зручна інтерполяція і багаторядковість | `Hello, ${name}!` |
| Деструктуризація | Просте витягання даних | const { name, age } = user; |
| Spread / Rest | Гнучке об'єднання і розділення | const all = [...arr1, ...arr2]; |
| Класи | Синтаксичний цукор над прототипами | class User { constructor(name) {} } |
| Параметри за замовчуванням | Прибрали перевірки на undefined | function f(a, b = 1) {} |
Окремо варто виділити let і const: вони прибрали найбільш болючу пастку var, коли змінна витікала з блоку, і зламали класичну задачу з var у циклі та setTimeout. Стрілкові функції зняли потребу в const self = this і в .bind(this).
Модулі import і export
До ES6 у JS не було стандартизованих модулів, доводилося використовувати:
- IIFE, тобто функції, що викликають самі себе,
- або зовнішні системи на кшталт CommonJS (Node.js), AMD чи RequireJS.
ES6 уперше ввів офіційну систему модулів:
// math.js
export const sum = (a, b) => a + b;
// main.js
import { sum } from './math.js';Це стало основою для сучасних інструментів: Webpack, Rollup, Vite, Parcel, Next.js і так далі. Важлива деталь: модулі ES6 статичні, тобто набір імпортів відомий до виконання. Саме тому збирачі вміють робити tree shaking і викидати невикористаний код, чого CommonJS з його динамічним require() не дозволяє.
Promise і кінець callback hell
До ES6 асинхронний код виглядав жахливо, це називали «callback hell»:
getData(function (res) {
process(res, function (result) {
save(result, function () {
console.log('Done');
});
});
});ES6 приніс Promise, а з ним лінійний і читабельний код:
getData()
.then(process)
.then(save)
.then(() => console.log('Done'));Проміси дали також єдиний спосіб обробки помилок через .catch() замість окремого аргументу err у кожному колбеку. Пізніше, в ES2017, на їхній основі з'явився синтаксис async/await, який працює поверх тих самих промісів.
Об'єкти, масиви, символи, ітератори й генератори
Розширені можливості об'єктів і масивів:
- покращені літерали об'єктів: скорочений запис властивостей і методів, обчислювані ключі,
- нові методи
Array.from(),Array.of(),Object.assign(), - нові структури даних
Map,Set,WeakMap,WeakSet.
const obj = { a: 1, b: 2 };
const copy = Object.assign({}, obj);
const key = 'dynamic';
const built = { [key]: 1, copy };Рівнем нижче лежить механіка самої мови:
Symbolце новий примітивний тип даних, зокрема для унікальних ключів і протоколів на кшталтSymbol.iterator,IteratorіGeneratorце основа дляfor...of,yieldі, зрештою, дляasync/await.
function* counter() {
yield 1;
yield 2;
yield 3;
}
for (const num of counter()) console.log(num);Уніфікація середовищ і підсумок
ES6 зробив мову універсальною: Node.js, браузери й фронтенд-фреймворки почали говорити однією мовою, з'явилися стандартизовані збирачі, транспілятори (Babel) і фреймворки (React, Vue, Angular), які спираються на модулі й класи зі стандарту.
| Причина | Коротко |
|---|---|
| Новий сучасний синтаксис | Зробив JS зручним і безпечнішим |
| Модулі | Навели лад у структурі проєктів |
Асинхронність через Promise | Прибрала callback hell |
| Нові структури даних | Підвищили ефективність і виразність |
| Уніфікація середовищ | JS став серйозною мовою і на фронтенді, і на бекенді |
Простіше кажучи: до ES6 JavaScript сприймали як «іграшку для браузера», після ES6 це сучасна, потужна й зріла мова, що стоїть в одному ряду з Python, Java і C#.
Типові помилки
- Вважати, що
letіconstне мають hoisting. Вони теж підіймаються, але потрапляють у temporal dead zone, тому звернення до них до оголошення кидаєReferenceError. - Плутати
constз незмінністю.constзабороняє перепризначення, але вміст об'єкта чи масиву змінювати можна; для незмінності потрібенObject.freeze()або структурне копіювання. - Використовувати стрілкову функцію як метод об'єкта чи конструктор. У неї немає власного
this,argumentsіprototype, томуnewз нею не працює. - Плутати модулі ES6 з CommonJS.
importстатичний і асинхронний,require()синхронний; змішування двох систем в одному файлі дає помилки збірки. - Думати, що клас це нова модель успадкування.
classце синтаксичний цукор над прототипами, під ним та сама прототипна модель. - Вважати, що
Promiseробить код паралельним. Він лише впорядковує асинхронність; для одночасних операцій потрібенPromise.all()чиPromise.allSettled().
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.