Содержание
- Top-level await
- autoplay
- Class field declarations
- RegExp match indices
- Error cause
- .at()
- hasOwn
hasOwn, .at(), indices и другие важные изменения.
Top-level await
Теперь можно использовать await
для модулей на верхних уровнях. Раньше await
нельзя было использовать вне функций.
const response = await fetch('https://example.com');
const text = await response.text();
Два важнейших преимущества top-level await
:
- Гарантия того, что модули не получат доступ к асинхронному импорту, пока они не будут полностью инициализированы;
- Прозрачная обработка асинхронности: импортёрам не нужно знать, является ли импортируемый модуль асинхронным или нет.
Также это позволит загружать модули условно:
if(download) {
await require('/special-code-for-2023-year.js')
}
Или позволит просто указать ссылку до другого ресурса, если с первым произошла ошибка:
let lodash;
try {
lodash = await import('https://primary.example.com/lodash');
} catch {
lodash = await import('https://secondary.example.com/lodash');
}
Также можно использовать тот ресурс, который загрузился быстрее:
const resource = await Promise.any([
fetch('http://example.com/first.txt')
.then(response => response.text()),
fetch('http://example.com/second.txt')
.then(response => response.text()),
]);
Из-за Promise.any()
, переменная resource
инициализируется через ту загрузку, которая завершится первой.
Элементы класса
Приватные поля и методы.
class ClassName {
// вместо: constructor() { this.publicNumber = 34; }
publicNumber = 34; // публичное поле
// вместо: static get staticPublicField() { return -1 }
static staticPublicField = 'Публично'; // статическое публичное поле
static #staticPrivateField = 'Приватно'; // статическое приватное поле
#privateMethod() {} // приватный метод
// выполняется при создании класса
static {
// статический блок
}
}
x in obj
class Color {
#name;
constructor(name) {
this.#name = name;
}
static check(obj) {
return #name in obj;
}
}
Indices
Если добавить флаг /dк
регулярному выражению, его использование создаст объекты
сопоставления, которые записывают начальный и конечный индексы каждого
захвата группы. Indices
предоставляет дополнительную информацию о начальных и конечных индексах захваченных подстрок относительно начала входной строки.
const execArray = /(a+)(b+)/d.exec('aaaabb');
execArray[1]; // aaaa
execArray.indices[1]; // [0, 4]
execArray[2]; // bb
execArray.indices[2]; // [4, 6]
error. cause или цепочки ошибок
Errorи
его подклассы теперь позволяют узнать, какая ошибка вызвала текущую. Это позволяет облегчить диагностику приложения. Свойство .cause()
в Error
позволяет указать какая ошибка вызвала другую ошибку.
try {
// сделать что-нибудь
} catch (otherError) {
throw new Error('Это другая ошибка', {cause: otherError});
}
function readFiles(filePaths) {
return filePaths.map(
(filePath) => {
try {
// ···
} catch (otherError) {
throw new Error(
`While processing ${filePath}`,
{cause: otherError}
);
}
});
}
.at()
Метод .at()
позволяет читать элемент по заданному индексу, как оператор [ ]
, и поддерживает отрицательный индекс, в отличие от оператора [ ]
. Работает со всеми индексируемыми классами Array, String и TypedArrays.
Основная задача у .at()
иметь возможность выполнять «отрицательную индексацию» и упростить сложившиеся паттерны arr[arr.length -N]
и arr.slice(-N)[0]
. У arr[arr.length - N]
есть очевидный минус: нельзя работать с анонимными значениями.
Так как в JavaScript реализовать arr[-N]
уже невозможно, решено было сделать методом arr.at(-N)
.
['a', 'b', 'c', 'd'].at(1); // 'b'
['a', 'b', 'c', 'd'].at(-1); // 'd'
const string = "1234"
string.at(-2) // '3'
hasOwn
Object.hasOwn(obj, prop)
это безопасный способ проверить, есть ли у объекта собственное, не унаследованное, свойство, с помощью ключа prop
.
const parent = {
parentKey: 'parentValue'
}
const child = {
__proto__: parent,
childKey: 'childValue'
}
Object.hasOwn(child, 'parentKey'); //false
Object.hasOwn(parent, 'parentKey'); //true
hasOwn
работает стабильнее, так как подходит для объектов созданных с помощью .create()
.
let person = Object.create(null);
person.name = 'Nikolai';
Object.hasOwn(person, 'name'); // true
person.hasOwnProperty('name'); // ошибка
Хотя в этом случае `hasOwnProperty` можно починить с помощью Object.prototype.hasOwnProperty.call
:
Object.prototype.hasOwnProperty.call(person, 'name') // true