Перейти к основному содержимому

Высокоуровневый `await`

· 4 мин. чтения
Майлз Боринс ([@MylesBorins](https://twitter.com/MylesBorins))

Высокоуровневый await позволяет разработчикам использовать ключевое слово await за пределами асинхронных функций. Он действует как большая асинхронная функция, заставляя другие модули, которые их import, ожидать перед началом выполнения своего тела.

Оператор объединения с null

· 7 мин. чтения
Джастин Риджвелл

Предложение об операторе объединения с null (??) добавляет новый оператор краткого замыкания, предназначенный для обработки значений по умолчанию.

Вы, возможно, уже знакомы с другими операторами краткого замыкания && и ||. Оба этих оператора работают с "истинными" и "ложными" значениями. Представьте следующий пример: lhs && rhs. Если lhs (читаем как "левая сторона") является ложным значением, выражение оценивается как lhs. В противном случае оно оценивается как rhs (читаем как "правая сторона"). Для примера lhs || rhs действует обратное правило. Если lhs является истинным значением, выражение оценивается как lhs. В противном случае оно оценивается как rhs.

Опциональная цепочка

· 4 мин. чтения
Майя Армянова ([@Zmayski](https://twitter.com/Zmayski)), разрыватель опциональных цепочек

Длинные цепочки доступа к свойствам в JavaScript могут быть рискованными, так как любое из них может оцениваться как null или undefined (также известные как "значения nullish"). Проверка существования свойства на каждом шаге легко превращается в глубокую вложенную структуру if-условий или длинное if-условие, воспроизводящее цепочку доступа к свойствам:

Подмножество JSON, также известное как JSON ⊂ ECMAScript

· 6 мин. чтения
Матиас Биненс ([@mathias](https://twitter.com/mathias))

Благодаря предложению JSON ⊂ ECMAScript, JSON стал синтаксическим подмножеством ECMAScript. Если вас удивляет, что это не было так ранее, вы не одиноки!

Старое поведение из ES2018

В ES2018 строковые литералы ECMAScript не могли содержать неизбежные символы U+2028 LINE SEPARATOR и U+2029 PARAGRAPH SEPARATOR, поскольку они считаются разделителями строк даже в таком контексте:

// Строка, содержащая необработанный символ U+2028.
const LS = '
';
// → ES2018: SyntaxError

// Строка, содержащая необработанный символ U+2029, созданная с помощью `eval`:
const PS = eval('"\u2029"');
// → ES2018: SyntaxError

Это проблематично, потому что строки JSON могут содержать эти символы. В результате разработчики были вынуждены реализовать специальную логику постобработки при встраивании допустимого JSON в программы ECMAScript для обработки этих символов. Без такой логики в коде могли быть тонкие ошибки или даже проблемы безопасности!

`Intl.NumberFormat`

· 4 мин. чтения
Маттиас Байненс ([@mathias](https://twitter.com/mathias)) и Шейн Ф. Карр

Вы, возможно, уже знакомы с API Intl.NumberFormat, так как его поддержка существует в современных средах уже некоторое время.

В своей самой базовой форме Intl.NumberFormat позволяет создавать экземпляр форматтера, поддерживающий форматирование чисел с учетом локали. Так же, как и другие API Intl.*Format, экземпляр форматтера поддерживает методы format и formatToParts:

`globalThis`

· 2 мин. чтения
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Если вы писали JavaScript для использования в веб-браузере, возможно, вы использовали window для доступа к глобальному объекту this. В Node.js вы могли использовать global. Если вы писали код, который должен работать в обеих средах, вы могли определить, какой из них доступен, и затем использовать его — но список идентификаторов, которые нужно проверять, растет с увеличением числа окружений и случаев использования. Это быстро выходит из-под контроля:

Слабые ссылки и финализаторы

· 9 мин. чтения
Сатья Гунасекаран ([@_gsathya](https://twitter.com/_gsathya)), Матиас Биненс ([@mathias](https://twitter.com/mathias)), Шу-ю Го ([@_shu](https://twitter.com/_shu)) и Лешек Свирски ([@leszekswirski](https://twitter.com/leszekswirski))

В общем случае ссылки на объекты в JavaScript являются сильно удерживаемыми, что означает, что пока у вас есть ссылка на объект, он не будет удален сборщиком мусора.

const ref = { x: 42, y: 51 };
// Пока у вас есть доступ к `ref` (или любой другой ссылке на
// тот же объект), объект не будет удален сборщиком мусора.

На данный момент WeakMap и WeakSet являются единственными способами частично слабой ссылки на объект в JavaScript: добавление объекта в качестве ключа в WeakMap или WeakSet не предотвращает его удаление сборщиком мусора.

const wm = new WeakMap();
{
const ref = {};
const metaData = 'foo';
wm.set(ref, metaData);
wm.get(ref);
// → metaData
}
// У нас больше нет ссылки на `ref` в этой области видимости блока, поэтому он
// может быть удален сборщиком мусора, даже если он является ключом в `wm`, к
// которому у нас все еще есть доступ.

Стабильная `Array.prototype.sort`

· 3 мин. чтения
Mathias Bynens ([@mathias](https://twitter.com/mathias))

Допустим, у вас есть массив собак, где каждая собака имеет имя и рейтинг. (Если это кажется странным примером, знайте, что существует аккаунт в Twitter, который специализируется именно на этом… Не спрашивайте!)

// Обратите внимание, что массив предварительно отсортирован по алфавиту по `name`.
const doggos = [
{ name: 'Abby', rating: 12 },
{ name: 'Bandit', rating: 13 },
{ name: 'Choco', rating: 14 },
{ name: 'Daisy', rating: 12 },
{ name: 'Elmo', rating: 12 },
{ name: 'Falco', rating: 13 },
{ name: 'Ghost', rating: 14 },
];
// Сортируем собак по рейтингу в порядке убывания.
// (Это обновляет `doggos` на месте.)
doggos.sort((a, b) => b.rating - a.rating);

`Symbol.prototype.description`

· 1 мин. чтения
Mathias Bynens ([@mathias](https://twitter.com/mathias))

В JavaScript для Symbol можно задать описание при создании:

const symbol = Symbol('foo');
// ^^^^^

Ранее единственным способом программно получить это описание был непрямой вызов Symbol.prototype.toString():

const symbol = Symbol('foo');
// ^^^^^
symbol.toString();
// → 'Symbol(foo)'
// ^^^
symbol.toString().slice(7, -1); // 🤔
// → 'foo'

Однако этот код выглядит немного магически, не очень очевиден и нарушает принцип «выражать намерение, а не реализацию». Кроме того, данный метод не позволяет отличить символ без описания (например, Symbol()) от символа с пустой строкой в качестве описания (например, Symbol('')).

`Object.fromEntries`

· 3 мин. чтения
Матиас Биненс ([@mathias](https://twitter.com/mathias)), шептун JavaScript

Object.fromEntries — это полезное дополнение к встроенной библиотеке JavaScript. Перед тем как объяснить, что он делает, важно понять существующий API Object.entries.

Object.entries

API Object.entries существует уже некоторое время.

Для каждой пары ключ-значение в объекте Object.entries предоставляет массив, где первый элемент — это ключ, а второй элемент — значение.

Object.entries особенно полезен в сочетании с for-of, так как он позволяет элегантно проходить по всем парам ключ-значение в объекте:

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

for (const [key, value] of entries) {
console.log(`Значение ${key} равно ${value}.`);
}
// Результат:
// Значение x равно 42.
// Значение y равно 50.

К сожалению, нет простого способа преобразовать результат entries обратно в эквивалентный объект… до настоящего момента!

Object.fromEntries

Новый API Object.fromEntries выполняет обратное преобразование от Object.entries. Это делает легким восстановление объекта на основе его пар:

const object = { x: 42, y: 50 };
const entries = Object.entries(object);
// → [['x', 42], ['y', 50]]

const result = Object.fromEntries(entries);
// → { x: 42, y: 50 }

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

const object = { x: 42, y: 50, abc: 9001 };
const result = Object.fromEntries(
Object.entries(object)
.filter(([ key, value ]) => key.length === 1)
.map(([ key, value ]) => [ key, value * 2 ])
);
// → { x: 84, y: 100 }

В этом примере мы фильтруем объект, чтобы оставить только ключи длиной 1, то есть только ключи x и y, исключая ключ abc. Затем мы преобразуем оставшиеся пары и возвращаем обновленные пары ключ-значение для каждой. В этом примере мы удваиваем каждое значение, умножая его на 2. Конечный результат — новый объект, содержащий только свойства x и y с новыми значениями.