Версии JavaScript – ключевые изменения и практические примеры

Раздел: JavaScript -> Версии JavaScript

Понимание версий JavaScript

Язык JavaScript развивается через стандартизированные версии, также известные как ECMAScript (ES). Каждая версия вводит новые синтаксические конструкции, API и улучшения. Знание версий помогает писать современный, читаемый и производительный код, а также обеспечивать совместимость с целевыми окружениями.

Основное решение: транспиляция для кросс-версионной совместимости

Как сделать код на ES2024 работающим в старых браузерах?

Используется связка Babel (транспилятор) и полифиллов (например, core-js). Babel преобразует современный синтаксис в ES5-совместимый, а полифиллы добавляют отсутствующие встроенные объекты и методы.

// Исходный код (ES2020)
const user = { name: 'Mike', age: 30 };
console.log(user?.address?.city ?? 'Не указан');

Js 7 (javascript es7)

// Результат транспиляции Babel с @babel/preset-env
var user = { name: 'Mike', age: 30 };
console.log((user === null || user === void 0 ? void 0 : (user.address === null || user.address === void 0 ? void 0 : user.address.city)) !== null && _result !== void 0 ? _result : 'Не указан');

версия js (версия javascript)

Проблема: неправильная настройка targets в Babel приводит к избыточному или недостаточному транспилированию. Решение: явно указать список браузеров в browserslist.

Варианты решений

Вариант 1. Как определить версию JavaScript, поддерживаемую текущим браузером?

Можно выполнить проверку наличия конкретных фич, а не самой версии. Например, проверить Symbol (ES6) или globalThis (ES2020).

// Проверка поддержки Optional Chaining (ES2020)
try {
  eval('const obj = {}; obj?.prop');
  console.log('Optional chaining поддерживается');
} catch (e) {
  console.log('Optional chaining не поддерживается');
}

Типичная ошибка: использование eval небезопасно и может блокироваться политикой безопасности. Альтернатива: проверить через 'optionalChaining' in document.createElement('div') или использовать библиотеку feature-detect.

Вариант 2. Как написать код, совместимый с ES5 и более новыми версиями?

Применять строгий режим ("use strict") и избегать конструкций, не поддерживаемых в ES5 (например, let, const, стрелочные функции, классы). Для современного кода использовать транспиляцию.

// Код, работающий в ES5 и выше
var sum = function(a, b) {
  "use strict";
  return a + b;
};
console.log(sum(2, 3)); // 5

Проблема: ручная поддержка двух версий увеличивает объём кода и риск ошибок. Решение: писать на современном JS и автоматически транспилировать.

Вариант 3. Как использовать модули ES6 (ESM) с поддержкой старых браузеров?

Современные браузеры поддерживают <script type="module">. Для старых – подключать транспилированные бандлы через Webpack или Rollup с атрибутом nomodule.

<!-- Для современных браузеров -->
<script type="module" src="app.js"></script>
<!-- Для старых (запасной вариант) -->
<script nomodule src="legacy-app.js"></script>

Ошибка: старые браузеры, не поддерживающие nomodule, могут загрузить оба скрипта. Решение: добавлять проверку через @babel/preset-env с настройкой modules: 'systemjs'.

Расширенные примеры по версиям JavaScript

Пример 1. ES5 и ES6 – разница в объявлении переменных

Пример
// ES5 (var – функциональная область видимости)
if (true) {
  var x = 10;
}
console.log(x); // 10 (утечка)

// ES6 (let – блочная область видимости)
if (true) {
  let y = 20;
}
// console.log(y); // ReferenceError
Вывод: в ES5 переменная доступна вне блока, в ES6 – нет.

Пример 2. Стрелочные функции (ES6) и обычные функции (ES5)

Пример
// ES5
var multiply = function(a, b) {
  return a * b;
};

// ES6
const multiply = (a, b) => a * b;

console.log(multiply(4, 5)); // 20
Стрелочная функция короче, не имеет собственного this и arguments.

Пример 3. Итерация по массиву – forEach (ES5) vs for...of (ES6)

Пример
const arr = [1, 2, 3];
// ES5
arr.forEach(function(item) {
  console.log(item);
});

// ES6
for (const item of arr) {
  console.log(item);
}
Оба выведут 1, 2, 3. for...of позволяет использовать break/continue.

Пример 4. Параметры по умолчанию (ES6)

Пример
// ES5
function greet(name) {
  name = name || 'Гость';
  return 'Привет, ' + name;
}

// ES6
const greet = (name = 'Гость') => `Привет, ${name}`;

console.log(greet()); // Привет, Гость
console.log(greet('Анна')); // Привет, Анна
В ES6 значения по умолчанию вычисляются только при undefined, а не при любом falsy.

Пример 5. Async/await (ES2017) и цепочка промисов (ES6)

Пример
// ES6 – цепочка then
fetch('/api/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

// ES2017 – async/await
async function loadData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}
loadData();
Async/await делает асинхронный код похожим на синхронный, улучшая читаемость.

Пример 6. Nullish coalescing (ES2020) и ленивое логическое ИЛИ

Пример
const value = null;
// ES5 – логическое ИЛИ
const resultA = value || 'по умолчанию';
console.log(resultA); // 'по умолчанию'

// ES2020 – nullish coalescing
const resultB = value ?? 'по умолчанию';
console.log(resultB); // 'по умолчанию'

// Различие: для 0 или '' (falsy)
const num = 0;
console.log(num || 10); // 10 (нежелательно)
console.log(num ?? 10); // 0 (правильно)
Nullish coalescing обрабатывает только null и undefined, а не все falsy значения.

Пример 7. Optional chaining (ES2020) для безопасного доступа к свойствам

Пример
const user = { profile: { email: 'test@test.com' } };
// ES5 – проверка на каждом уровне
var email = user && user.profile && user.profile.email || 'нет почты';
// ES2020
const email2 = user?.profile?.email ?? 'нет почты';
console.log(email2); // test@test.com
Optional chaining сокращает код и предотвращает TypeError.

Пример 8. Проверка поддержки версии с помощью typeof

Пример
// ES6: Symbol
if (typeof Symbol !== 'undefined') {
  console.log('Symbol поддерживается');
}

// ES2017: Object.values
if (typeof Object.values === 'function') {
  console.log('Object.values поддерживается');
}

// ES2020: globalThis
if (typeof globalThis !== 'undefined') {
  console.log('globalThis поддерживается');
} else {
  // полифилл для старых окружений
  window.globalThis = window;
}

Версия JavaScript - comments

En
версия js (javascript)