DevKucher;

10 новых функций ES2020, которые вы должны знать

Изображение на обложке для 10 новых функций ES2020, которые вы должны знать
  1. #1 BigInt
  2. #2: Динамический импорт
  3. #3: Nullish Coalescing
  4. #4: Оператор опциональной последовательности
  5. #5: Promise.allSettled
  6. #6: String#matchAll
  7. #7: globalThis
  8. #8: Экспорт модуля
  9. #9: Стандарт порядка выполнения для for-in
  10. #10: import.meta

Комитет TC39 недавно одобрил кандидатуру ECMAScript 2020 (широко известную как ES2020), которая содержит завершенный набор функций, входящий в язык JavaScript. Эта кандидатура должна быть рассмотрен и утверждена Генеральной ассамблеей ECMA в июне этого года. Большинство новых функций уже реализованы в браузерах и могут транспилироваться с помощью Babel. Это означает, что теперь у нас есть полное представление об изменениях, новой и улучшенной спецификации JavaScript. Давайте посмотрим, что это за изменения.

#1 BigInt

BigInt - одна из самых ожидаемых функций в JavaScript наконец-то здесь. Я не буду вдаваться в технические подробности, но из-за того как Javascript обрабатывает числа, когда вы начинаете работать с большими числами у вас возникает проблема с точностью расчетов. Числа так сказать стают не устойчивыми.

На данный момент максимальное число, которое вы можете получить в Javascript, равно (2^53) - 1 = 9007199254740991, мы можем его увидеть с помощью MAX_SAFE_INTEGER:

const max = Number.MAX_SAFE_INTEGER;

console.log(max); // 9007199254740991

Все числа что больше его становятся немного "не стабильным"

console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740992
console.log(max + 3); // 9007199254740994
console.log(Math.pow(2, 53) == Math.pow(2, 53) + 1); // true

И здесь нам приходит на помощь BigInt. Добавив букву «n» в конце, мы можем использовать и взаимодействовать с безумно большими числами. Мы не можем смешивать стандартные числа с числами BigInt, поэтому любые математические расчеты нужно будет делать только с BigInt.

const bigNum = 100000000000000000000000000000n;

console.log(bigNum * 2n); // 200000000000000000000000000000n

Подробнее на MDN

#2: Динамический импорт

Динамический импорт в JavaScript дает вам возможность динамически импортировать файлы JS в виде модулей в вашем приложении. Сейчас подобным образом мы можем это делать с помощью Webpack и Babel.

Если у вас есть файл со служебными функциями, некоторые из них могут использоваться редко, а импорт всех их зависимостей может быть просто пустой тратой ресурсов. Теперь мы можем использовать async/await для динамического импорта наших зависимостей. Таким образом мы импортируем модуль только когда он нам нужен.

// utils.js
const add = (a, b) => a + b;

// index.js
const doMath = async (num1, num2) => {
  if (num1 && num2) {
    const utils = await import('./utils.js');
    return utils.add(num1, num2);
  }
};

Подробнее на exploringjs

#3: Nullish Coalescing

Nullish Coalescing добавляет возможность действительно проверять нулевые значения вместо ложных значений. Вы можете спросить, в чем разница между нулевыми и ложными значениями?

В JavaScript многие значения являются ложными, например, пустые строки, число 0, undefined, null, false, NaN и т.д.

Тем не менее, во многих случаях вы можете захотеть проверить, является ли переменная нулевой, то есть если она не определена или равна нулю, например, когда переменная может иметь пустую строку или даже ложное значение.

В этом случае вы будете использовать новый нулевой оператор - ??

let user = {
  info: {
    name: '',
    age: 0,
  },
};

console.log(user.info.name || 'Anonymous'); // Anonymous
console.log(user.info.name ?? 'Anonymous'); // ""

console.log(user.info.age || 18); // 18
console.log(user.info.age ?? 18); // 0

Подробнее на MDN

#4: Оператор опциональной последовательности

Этот оператор (Optional Chaining) позволяет вам получить доступ к глубоко вложенным свойствам объекта, не беспокоясь о том, существует ли свойство или нет. Если оно существует - отлично давайте мне его. Если нет - получим undefined.

Это работает не только со свойствами объекта, но также с вызовами функций и массивами. Супер удобно! Вот пример:

const data = {
  user: {
    rating: 4.7,
  },
};

const userRating = data.user?.rating; // 4.7
const casperProp = data.user?.casper?.isGhost; // undefined
const catchCasper = data.user?.Ghostbusters?.catch?.(); // undefined

Подробнее на MDN

#5: Promise.allSettled

Метод Promise.allSettled() возвращает промис, который исполняется когда все полученные промисы завершены (исполнены или отклонены), содержащий массив результатов исполнения полученных промисов.

Это не было доступно изначально, хотя были некоторые близкие реализации, такие как race и all. Это приводит к тому, что «Просто сделаю все промисы, а на результаты мне плевать» для JavaScript.

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => {
  return window.setTimeout(reject, 100, 'foo');
});
const promises = [promise1, promise2];

Promise.allSettled(promises).then((results) =>
  results.forEach((result) => console.log(result.status))
);

// expected output:
// "fulfilled"
// "rejected"

Подробнее на MDN

#6: String#matchAll

matchAll - это новый метод, добавленный к прототипу String, который связан с регулярными выражениями. Он возвращает итератор по всем результатам при сопоставлении строки с регулярным выражением.

let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';

let array = [...str.matchAll(regexp)];

console.log(array[0]);
// expected output: Array ["test1", "e", "st1", "1"]

console.log(array[1]);
// expected output: Array ["test2", "e", "st2", "2"]

Подробнее на MDN

#7: globalThis

Если вы решитесь написать какой-то кроссплатформенный код на JS, который мог бы работать на Node, в браузере, а также внутри веб-воркеров, вам было бы трудно получить доступ к глобальному объекту.

Это потому, что для браузеров это window, для Node global и self для веб-воркеров.

ES2020 предоставляет нам globalThis, который всегда ссылается на глобальный объект независимо от того он выполняется:

globalThis.setTimeout = window.setTimeout; // true

Подробнее на MDN

#8: Экспорт модуля

В модулях JavaScript уже можно было использовать следующий синтаксис:

import * as utils from './utils.mjs';

Тем не менее, до сих пор не было никакого симметричного синтаксиса экспорта:

export * as utils from './utils.mjs';

Это эквивалентно следующему:

import * as utils from './utils.mjs';
export { utils };

Подробнее на MDN

#9: Стандарт порядка выполнения для for-in

В спецификации ECMA не было указано, в каком порядке следует выполнять for (x in y). Потому браузеры при реализации согласовали порядок самостоятельно. Теперь это официально стандартизировано в ES2020.

Подробнее на MDN

#10: import.meta

Объект import.meta это мета-свойство, указывающее мета-данные JavaScript модуля в зависимости от контекста. Он содержит информацию о модуле, например, URL модуля.

Рассмотрим модуль module.js:

<script type="module" src="module.js"></script>

Вы можете получить доступ к мета-информации об этом модуле, используя объект import.meta:

console.log(import.meta); // {url: "file: ///home/user/module.js"}

Это возвращает объект со свойством url показывающее базовый URL этого модуля. Это может быть либо URL с которого скрипт был получен (для внешних скриптов), либо базовый URL содержащего его документа (для внутренних скриптов).

Подробнее на MDN