ECMAScript 6: что принёс и что было после него
Содержание
О проверке кода. Примеры не запускались — в отличие от материалов по Node.js, где приводится фактический вывод. Говорим прямо, а не ставим бейдж «проверено» без проверки.
ES6 — самое значимое обновление в истории языка и одновременно источник вечной путаницы в названиях. Разберём и то, и другое.
Сначала про имя
ES6 и ES2015 — это один и тот же стандарт. Не две версии, не «шестая и пятнадцатая».
До 2015 года выпуски нумеровали по порядку: ES3, ES5. Шестой готовили почти десять лет, он получился огромным — и все привыкли звать его ES6. А в момент выхода комитет сменил схему: теперь стандарт выходит ежегодно и называется по году. Так ES6 официально стал ES2015.
| Разговорное | Официальное | Год |
|---|---|---|
| ES5 | ECMAScript 5 | 2009 |
| ES6 | ES2015 | 2015 |
| ES7 | ES2016 | 2016 |
| — | ES2017 | 2017 |
| — | ES2024 | 2024 |
После ES2015 разговорные номера умерли: «ES7» ещё говорят, «ES12» — уже нет. Подробнее про соотношение JavaScript и ECMAScript — в отдельном разборе.
Что принёс ES6
let и const вместо var
var x = 1; // виден во всей функции, всплывает наверх
let y = 2; // живёт только в своём блоке {}
const z = 3; // то же, но переприсвоить нельзя
Разница не косметическая. var всплывает (hoisting) и виден во всей функции, из-за чего появлялась классическая ошибка:
// ❌ все три колбэка напечатают 3
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i));
}
// ✅ let создаёт новую переменную на каждой итерации
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 0, 1, 2
}
const не делает значение неизменяемым — он запрещает переприсваивать саму переменную. Объект под const менять можно:
const user = { name: 'Аня' };
user.name = 'Борис'; // ✅ работает
user = {}; // ❌ TypeError
Правило: по умолчанию const, let — если значение меняется, var — никогда.
Стрелочные функции: дело не в краткости
const double = (x) => x * 2;
[1, 2, 3].map((x) => x * 2);
Короче — приятный побочный эффект. Главное в стрелке — у неё нет своего this. Она берёт его из окружающего кода.
// ❌ обычная функция: свой this, здесь undefined
const timer = {
seconds: 0,
start() {
setInterval(function () {
this.seconds++; // this — не timer!
}, 1000);
},
};
// ✅ стрелка: this взят снаружи, это timer
start() {
setInterval(() => {
this.seconds++;
}, 1000);
}
До ES6 это лечили строкой var self = this; — её видно в любом коде тех лет.
Оборотная сторона: методом объекта стрелка быть не должна. this внутри неё будет не объектом, а тем, что снаружи.
Деструктуризация
const { name, age = 18 } = user; // из объекта, со значением по умолчанию
const [first, ...rest] = [1, 2, 3]; // из массива
function greet({ name, city }) { } // прямо в параметрах
Одна из тех вещей, после которых старый код читать больно.
Шаблонные строки
const msg = `Привет, ${name}! Тебе ${age} лет.`;
const html = `
многострочный текст
без \n и склейки
`;
⚠️ Важно: шаблонная строка не экранирует ничего. Собрать в ней HTML из данных пользователя и вставить через innerHTML — это XSS. Удобство подстановки к безопасности отношения не имеет.
Классы
class User {
#secret = 'приватное поле'; // это уже не ES6, а ES2022
constructor(name) { this.name = name; }
greet() { return `Привет, ${this.name}`; }
}
Класс в JavaScript — синтаксический сахар над прототипами. Никакого нового механизма наследования не появилось: под капотом те же прототипы, просто запись человеческая.
Промисы
Самое важное для серверной разработки. Промисы в ES6 стали частью языка — до этого их приносили библиотеки вроде Bluebird и Q. Подробный разбор с замерами — в статье про промисы в Node.js.
Модули
import { readFile } from 'node:fs/promises';
export function helper() { }
import/export появились в ES6, но реально заработали намного позже: в браузерах — с 2018 года, в Node — ещё позже. Это редкий случай, когда стандарт сильно опередил реализацию.
Что было после ES6
-
1
ES2015 (ES6)Огромный скачок:
let, стрелки, классы, промисы, модули -
2
ES2017
async/await— то, ради чего промисы стали читаемыми -
3
ES2020
Promise.allSettled, опциональная цепочка?.,?? -
4
ES2021—2022
Promise.any, приватные поля#,at(), top-level await -
5
ES2023—2024
toSorted()без мутации,Object.groupBy()
Годовой цикл изменил отношение к версиям. Раньше ждали большой релиз и потом год переписывали код. Теперь каждый год приезжает пара методов, их подхватывают за минуту, и никто не считает номера.
Практический вывод: гоняться за версиями не нужно. Учить надо промисы и модули — это фундамент. Array.at() или Object.groupBy() осваиваются за минуту, когда понадобятся.
Нужен ли Babel
Короткий ответ: для ES6 — нет.
В 2017-м Babel стоял в каждом проекте: он превращал стрелки и let обратно в ES5, потому что Internet Explorer их не понимал. Это была обязательная часть сборки.
Сегодня все живые браузеры и все поддерживаемые версии Node понимают ES2020+ нативно. Транспиляция нужна ровно в двух случаях: очень свежие предложения стандарта или аудитория на реликтовых браузерах. Оба — редкость.
Что было на этой странице в 2017 году
Первая версия вышла 24 марта 2017 года и называлась «Новые возможности ES6». Слово «новые» — точный снимок момента: тогда ES6 действительно был новинкой, которую внедряли с осторожностью, а Babel был обязателен.
Что изменилось:
- ES6 перестал быть новостью. Это просто язык. Отдельная статья про его возможности сегодня имеет смысл как исторический разбор, а не как «что нового».
- Babel из обязательного стал редким. Вся инфраструктура вокруг «как использовать ES6 сегодня» испарилась вместе с задачей.
- Появилось девять годовых выпусков после него — и ни один не сравним по масштабу. ES6 остался последним большим скачком в истории языка.
Мы оставили разбор возможностей — по этому запросу приходят те, кто разбирается в старом коде или готовится к собеседованию, — но добавили то, чего в 2017-м быть не могло: что случилось после.
Смежные темы: что такое JavaScript — язык, стандарт и среда; промисы и async/await — с замерами; массивы; уроки JavaScript.
Частые вопросы
ES6 и ES2015 — это разные стандарты?
Нужен ли Babel в 2026?
Чем `let` отличается от `var`, если оба объявляют переменную?
var виден во всей функции и всплывает наверх (hoisting), let живёт только в своём блоке {}. Отсюда классическая ошибка с var в цикле, где все колбэки получали последнее значение.Стрелочная функция — это просто короткая запись?
this: она берёт его из окружающего кода. Поэтому она отлично подходит для колбэков и не годится для методов объекта.Что учить после ES6?
Array.at() или Object.groupBy() подхватываются за минуту.