Что нового в ES2018 JavaScript

Что нового в ES2018 JavaScript

От автора: в этой статье я расскажу о новых возможностях, представленных через ES2018 JavaScript (ES9), с примерами того, для чего они предназначены и как их использовать.

JavaScript (ECMAScript) — это постоянно развивающийся стандарт, реализуемый многими поставщиками на нескольких платформах. ES6 (ECMAScript 2015) был крупным релизом, которому потребовалось на завершение шесть лет. Был разработан новый годовой график релизов, чтобы ускорить процесс и быстрее добавлять новые функции. ES9 (ES2018) — последняя итерация на момент написания данной статьи.

Технический комитет 39 (TC39) состоит из сторон, включающих поставщиков браузеров, которые собираются для продвижения предложений JavaScript в соответствии со строгой процедурой:

Этап 0: идеи —

Первоначальное представление идей для новых или улучшенных функций ECMAScript.

Этап 1: предложение —

Формальный документ заявки, поддержанный хотя бы одним членом TC39, который включает примеры API, семантику языка, алгоритмы, потенциальные сложности, полифиллы и демонстрации.

Этап 2: черновик —

Исходная версия спецификации функции. Требуются две экспериментальные реализации функции, хотя может быть в транспиллере, таком как Babel.

Этап 3: кандидат —

Спецификация предложения пересматривается, и получаются отзывы от поставщиков браузеров.

Этап 4: окончательный —

Предложение готово для включения в ECMAScript. Функцию следует считать стандартом только после достижения этой стадии. Однако на реализацию в браузерах и на других платформах, например, Node.js, может потребоваться больше времени.

ES2016

В ES2016 был отлажен процесс стандартизации, поэтому он ввел только две небольшие функции:

Метод массива includes(), который возвращает true или false, когда значение содержится в массиве, и

Оператор экспоненции a ** b, который идентичен Math.pow(a, b).

ES2017

В ES2017 был представлен широкий спектр новых функций:

Асинхронные функции для более четкого синтаксиса Promise

Object.values () для извлечения массива значений из объекта, содержащего пары имя-значение

Object.entries(), который возвращает массив подмассивов, содержащих имена и значения в объекте

Object.getOwnPropertyDescriptors(), чтобы вернуть объект, определяющий дескрипторы свойств для собственных свойств другого объекта (.value, .writable, .get, .set, .configurable, .enumerable)

padStart() и padEnd () — элементы отступа строк

завершающие запятые в определениях объектов, объявлениях массивов и списках параметров функций

SharedArrayBuffer и Atomics для чтения и записи в разделяемые ячейки памяти (отключено в ответ на уязвимость Spectre).

ES2018

ECMAScript 2018 (или ES9, если вы предпочитаете старый формат) уже доступен. Следующие функции достигли этапа 4, хотя рабочие реализации в браузерах на момент написания могут быть на разных стадиях.

Асинхронная итерация

В какой-то момент потока async/await, вы пытаетесь вызвать асинхронную функцию внутри синхронного цикла. Например:

async function process(array) { for (let i of array) { await doSomething(i); }
}

Это не будет работать. Как и это:

async function process(array) { array.forEach(async i => { await doSomething(i); });
}

Сами циклы остаются синхронными и всегда будут выполняться перед их внутренними асинхронными операциями.

ES2018 представляет асинхронные итераторы, которые похожи на обычные итераторы, за исключением того, что метод next() возвращает Promise. Поэтому ключевое слово await можно использовать с циклами for … of для последовательного запуска асинхронных операций. Например:

async function process(array) { for await (let i of array) { doSomething(i); }
}

Promise.finally()

Цепочка Promise может либо успешно завершиться и достичь последней .then(), либо дать сбой и запустить блок .catch(). В некоторых случаях нам нужно запустить тот же код независимо от результата — например, для очистки, удаления диалогового окна, закрытия соединения с базой данных и т. д.

Прототип .finally() позволяет указать конечную логику в одном месте, а не дублировать ее в последних .then() и .catch():

function doSomething() { doSomething1() .then(doSomething2) .then(doSomething3) .catch(err => { console.log(err); }) .finally(() => { // заканчиваем здесь! });
}

Свойства Rest/Spread

ES2015 представил параметры rest и операторы spread. Трехточечная нотация (…) применяется только к операциям массива. Параметры rest преобразуют последние аргументы, переданные функции, в массив:

restParam(1, 2, 3, 4, 5); function restParam(p1, p2, ...p3) { // p1 = 1 // p2 = 2 // p3 = [3, 4, 5]
}

Оператор spread работает наоборот — преобразует массив в отдельные аргументы, которые могут быть переданы функции. Например, Math.max() возвращает наибольшее значение, учитывая любое количество аргументов:

const values = [99, 100, -1, 48, 16];
console.log( Math.max(...values) ); // 100

ES2018 обеспечивает аналогичный функционал rest/spread для деструктуризации объектов, а также массивов. Пример:

const myObject = { a: 1, b: 2, c: 3
}; const { a, ...x } = myObject;
// a = 1
// x = { b: 2, c: 3 }

Или вы можете использовать его для передачи значений функции:

restParam({ a: 1, b: 2, c: 3
}); function restParam({ a, ...x }) { // a = 1 // x = { b: 2, c: 3 }
}

Как и в случае массивов, вы можете использовать только один параметр rest в конце объявления. Кроме того, он работает только для верхнего уровня каждого объекта, но не для под-объектов. Оператор spread может использоваться в других объектах. Например:

const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { ...obj1, z: 26 };
// obj2 is { a: 1, b: 2, c: 3, z: 26 }

Вы можете использовать оператор spread для клонирования объектов (obj2 = { …obj1 };), но имейте в виду, что вы получаете только частичные копии. Если свойство содержит другой объект, клон будет ссылаться на тот же объект.

Именованные группы захвата регулярных выражений

Регулярные выражения JavaScript могут возвращать объект соответствия — подобное массиву значение, содержащее строки соответствия. Например, для анализа даты в формате ГГГГ-ММ-ДД:

const reDate = /([0-9]{4})-([0-9]{2})-([0-9]{2})/, match = reDate.exec('2018-04-30'), year = match[1], // 2018 month = match[2], // 04 day = match[3]; // 30

Это трудно для чтения, и изменение регулярного выражения также может изменить индексы объектов соответствия. ES2018 делает возможным именование групп с использованием обозначений ?<name> сразу после открытия скобки захвата (. Например:

const reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/, match = reDate.exec('2018-04-30'), year = match.groups.year, // 2018 month = match.groups.month, // 04 day = match.groups.day; // 30

Для любой именованной группы, которая не содержит соответствия, свойству присваивается значение undefined. Именованные группы захвата также могут использоваться в методах replace(). Например, для преобразования даты в формате ММ-ДД-ГГГГ в формат US:

const reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/, d = '2018-04-30', usDate = d.replace(reDate, '$<month>-$<day>-$<year>');

Утверждения регулярных выражений lookbehind

В настоящее время JavaScript поддерживает внутри регулярного выражения утверждения lookahead. Это означает, что должно быть найдено соответствие, но ничего не захватывается, и утверждение не включается в общую строку соответствия. Например, чтобы захватить символ валюты в цене:

const reLookahead = /\D(?=\d+)/, match = reLookahead.exec('$123.89'); console.log( match[0] ); // $

ES2018 вводит утверждения lookbehind, которые работают также, но для предыдущих совпадений. Поэтому мы можем захватывать значение цены и игнорировать символ валюты:

const reLookbehind = /(?<=\D)\d+/, match = reLookbehind.exec('$123.89'); console.log( match[0] ); // 123.89

Это положительное утверждение lookbehind; должен существовать нецифровой символ \D. Существует также отрицательное утверждение lookbehind, которое устанавливает, что значение не должно существовать. Например:

const reLookbehindNeg = /(?<!\D)\d+/, match = reLookbehind.exec('$123.89'); console.log( match[0] ); // null

Флаг регулярных выражений s (dotAll)

Регулярное выражение точка «.» соответствует любому одиночному символу, кроме возврата каретки. Флаг s изменяет это поведение, разрешая включать ограничители строк. Например:

/hello.world/s.test('hello\nworld'); // true

Переход к свойствам Unicode через регулярные выражения

До сих пор в регулярных выражениях нельзя было получить доступ к свойствам символа Unicode через встроенные средства. ES2018 добавляет переход к свойствам Unicode — в форме \p{…} и \P{…} — в регулярных выражениях, в которых установлен флаг u (unicode). Например:

const reGreekSymbol = /\p{Script=Greek}/u;
reGreekSymbol.test('π'); // true

Изменения в литералах шаблонов

Наконец, были удалены все синтаксические ограничения, связанные с переходам к последовательностям в литералах шаблонов.

Раньше \u запускал переход к unicode, \x запускал переход к хекс, а символ \, за которым следовали цифры, обозначал переход к восьмеричным значениям. Это делало невозможным создание определенных строк, таких как путь к файлу Windows C:\uuu\xxx\111. Для получения дополнительной информации обратитесь к документацию по литералам шаблонов MDN.

Это что касается ES2018, но работа над ES2019 уже началась. Есть ли какие-либо функции, которые вы отчаянно хотите увидеть в следующем году?

Автор: Craig Buckler

Источник: https://www.sitepoint.com/

Редакция: Команда webformyself.