Що нового в ES2018

7 хв. читання

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

Технічний комітет 39 (TC39) складається зі сторін — вендорів браузерів, які зустрічаються для просування пропозицій JavaScript:

Стадія 0: strawman – Першопочаткове представлення ідей.

Стадія 1: proposal – Офіційний документ пропозиції, що відстоюється принаймні одним членом комітету TC39 і містить приклади API.

Стадія 2: draft – Початкова версія специфікації функції з двома експериментальними реалізаціями.

Стадія 3: candidate – Специфікація пропозиції переглядається і збирається фідбек вендорів.

Стадія 4: finished – Пропозиція готова до включення в ECMAScript, але може знадобитися більше часу для її додавання в браузери та Node.js .

ES2016

ES2016 затвердив процес стандартизації, додавши лише дві невеликі функції:

  1. Метод масиву includes(), який повертає true або false, коли значення міститься в масиві;
  2. Оператор експонування a ** b, що ідентичний до Math.pow(a, b).

ES2017

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

  • Асинхронні функції для більш чіткого синтаксису промісів;
  • Object.values() для вилучення масиву значень з об'єкта, що містить пари ім'я-значення;
  • Object.entries(), котрий повертає масив підмасивів, які містять імена й значення в об'єкті;
  • Object.getOwnPropertyDescriptors() для повернення об'єкту, який визначає дескриптори властивостей для власних властивостей іншого об'єкту (.value, .writable, .get, .set, .configurable, .enumerable);
  • padStart() та padEnd(), обидва — елементи заповнення рядка;
  • Trailing commas у визначеннях об'єктів, оголошеннях масивів та списках параметрів функцій;
  • 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(), що повертає проміс. Тому ключове слово await може бути використано з циклами for … of для послідовного запуску асинхронних операцій. Наприклад:

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

Promise.Finally()

Ланцюжок промісів може або виконатись успішно й досягти кінцевого .then(), або завершитись невдачею й задіяти блок .catch(). У деяких випадках ви хочете запустити той самий код незалежно від результату — наприклад, для очищення, видалення діалогу, закриття з'єднання з базою даних тощо.

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

function doSomething() {
  doSomething1()
  .then(doSomething2)
  .then(doSomething3)
  .catch(err => {
    console.log(err);
  })
  .finally(() => {
    // finish here!
  });
}

Властивості 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(). Наприклад, для конвертації дати у потрібний формат:

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>');

Ретроспективні перевірки регулярних виразів

JavaScript підтримує опереджувальні перевірки всередині регулярних виразів. Це означає, що має відбутися збіг, але при цьому нічого не фіксується, і перевірка не включається в загальний рядок збіжності. Наприклад, для захоплення символу валюти з будь-якої ціни:

const
  reLookahead = /\\D(?=\\d+)/,
  match       = reLookahead.exec('$123.89');

console.log( match[0] ); // $

В ES2018 додали ретроспективні перевірки, які працюють так само, але для попередніх збігів. Тому можна захопити число з ціни й проігнорувати символ валюти:

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

console.log( match[0] ); // 123.89

Це додатна ретроспективна перевірка; має існувати не числове \\D. Також існує від'ємна ретроспективна перевірка, яка встановлює те, що значення не повинне існувати. Наприклад:

const
  reLookbehindNeg = /(?<!\\D)\\d+/,
  match           = reLookbehind.exec('$123.89');

console.log( match[0] ); // null

Прапор регулярного виразу S (DotAll)

Регулярний вираз крапка . збігається з будь-яким одиничним символом, окрім повертання каретки. Прапор s змінює цю поведінку, символи нового рядка стають дозволені. Наприклад:

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

Regular Expression Unicode Property Escapes

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

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

Налаштування шаблонних літералів

Нарешті, всі синтаксичні обмеження, пов'язані з escape-послідовностями у шаблонних літералах, були видалені.

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

Це все для ES2018, проте робота над ES2019 вже розпочата.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.6K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація