Главная Категории Контакты Поиск

Руководство по ES2017 (ES8)

Узнай всё о ECMAScript и функциях, добавленных в ES2017 (ES8).

JavaScript·18.04.2019·читать 4 мин 🤓·Автор: Alexey Myzgin

ECMAScript - это стандарт, на котором основан JavaScript, и его часто называют ES.

ECMAScript 2017 - 8 издание стандарта ECMA-262 (также известный как ES2017 или ES8), был завершен в июне 2017 года.

По сравнению с ES6, ES8 является маленьким выпуском для JavaScript, но всё же содержит очень полезные функции:

  • Заполнения строки
  • Object.values()
  • Object.entries()
  • getOwnPropertyDescriptors()
    • Когда это полезно
  • «Висячие» запятые
  • async/await или асинхронные функции
    • Несколько асинхронных функций
  • Разделяемая память и атомарные операции

Заполнения строки

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

ES2017 представляет два метода для строк padStart() и padEnd() - которые позволяют добавлять либо пустую строку, либо любую другую строку к началу или, концу исходной строки.

padStart(количествоСимволов [, строкаЗаполнения]);
padEnd(количествоСимволов [, строкаЗаполнения]);

Пример использования:

// padStart()

"test".padStart(4); // 'test'
"test".padStart(5); // ' test'
"test".padStart(8); // '    test'
"test".padStart(8, "abcd"); // 'abcdtest'
// padEnd()

"test".padEnd(4); // 'test'
"test".padEnd(5); // 'test '
"test".padEnd(8); // 'test    '
"test".padEnd(8, "abcd"); // 'testabcd'

Object.values()

Object.values() - это новая функция, которая похожа на Object.keys(), но возвращает массив, содержащий все значения свойств объекта, исключая любые значения в цепочке прототипов.

Например:

const person = { name: "Alex", age: 28 };
Object.values(person); // ["Alex", 28]

Object.values() также работает с массивами:

const people = ["Alex", "Julia"];
Object.values(people); // ["Alex", "Julia"]

Object.entries()

Object.entries() относится к Object.keys, но возвращает массив, содержащий все собственные свойства объекта, в виде массива пар [key, value].

Например:

const person = { name: "Alex", age: 28 };
Object.entries(person); // [['name', '"Alex"'], ['age', 28]]

Object.entries() также работает с массивами:

const people = ["Alex", "Julia"];
Object.entries(people); // [['0', 'Alex'], ['1', 'Julia']]

getOwnPropertyDescriptors()

Этот метод возвращает все собственные (не унаследованные) дескрипторы свойств объекта.

Любой объект в JavaScript имеет набор свойств, и каждое из этих свойств имеет дескриптор.

Дескриптор - это набор атрибутов свойства, состоящий из подмножества следующих:

  • value: значение свойства;
  • writable: true если свойство может быть изменено;
  • get: функция получения (геттер) для свойства, вызываемая при чтении свойства;
  • set: функция установки (сеттер) для свойства, вызываемая, когда для свойства установлено значение;
  • configurable: если false, свойство не может быть удалено, и любой атрибут не может быть изменен, кроме его значения;
  • enumerable: true, если свойство перечислимо;

Object.getOwnPropertyDescriptors(obj) принимает объект и возвращает все собственные дескрипторы свойств данного объекта.

Когда это полезно

ES6 предоставил нам Object.assign(), который копирует все перечисленные собственные свойства из одного или нескольких объектов и возвращает новый объект.

Однако есть проблема - он неправильно копирует свойства с атрибутами не по умолчанию.

Если объект, например, имеет только сеттер, то он неправильно копируется в новый объект с помощью Object.assign().

Например:

const person1 = {
  set name(newName) {
    console.log(newName);
  }
};

Это не сработает:

const person2 = {};
Object.assign(person2, person1);

А это будет работать:

const person3 = {};
Object.defineProperties(person3, Object.getOwnPropertyDescriptors(person1));

Ты можешь увидеть это с помощью простого консольного теста:

person1.name = "x";
("x");

person2.name = "x";

person3.name = "x";
("x");

у person2 нет сеттера, так как он не был скопирован.

То же самое ограничение касается мелких объектов клонирования с помощью Object.create().

«Висячие» запятые

Эта функция позволяет использовать запятые в объявлениях и в вызовах функций после последнего параметра функции:

const doSomething = (var1, var2,) => {
  //...
};

doSomething("test2", "test2",);

async/await или асинхронные функции

Более подробно об async/await здесь.

ES2017 представил концепцию асинхронных функций (async functions), и это самое важное изменение, представленное в этом издании ECMAScript.

async/await - абстракция более высокого уровня по сравнению с промисами.

Когда Promises были введены в ES6, они предназначались для решения проблемы с асинхронным кодом, и они это сделали. Но за 2 года, в течение которых ES6 и ES2017 были разделены стало ясно, что промисы не могут быть окончательным решением. Промисы были введены для решения известной проблемы “ад обратных вызовов”, но ввели сложность сами по себе и сложность синтаксиса.

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

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

Код, использующий асинхронные функции, может быть записан как:

function doSomethingAsync() {
  return new Promise(resolve => {
    setTimeout(() => resolve("I did something"), 3000);
  });
}

async function doSomething() {
  console.log(await doSomethingAsync());
}

console.log("Before");
doSomething();
console.log("After");

Приведенный выше код выведет в консоль браузера следующее:

Before
After
I did something // через 3 секунды

Несколько асинхронных функций

Асинхронные функции могут быть очень легко соединены в цепочку, а их синтаксис гораздо более читабелен, чем у промисов:

async function go() {
  const p1 = await fetch("https://api.github.com/users/oleksiimyzgin");
  const p2 = await fetch("https://api.github.com/users/leoyats");
}

go();

В примере выше сначала мы ждем пока выполнится p1, а потом уже p2.

Разделяемая память и атомарные операции

Разделяемая память (shared memory) и атомарные операции (atomics) - это огромный, довольно продвинутый функционал, который является основным улучшением движков JS.

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

Для этого мы задействуем новый тип глобального объекта SharedArrayBuffer, который по существу хранит данные в общем пространстве памяти. Таким образом, эти данные могут быть разделены между основным потоком JS и потоками web-worker.

WebWorkers предлагают протокол обмена сообщениями через события. Начиная с ES2017, мы можем создавать массив разделяемой памяти между web-workers и их создателями, используя SharedArrayBuffer.

Поскольку неизвестно, сколько времени занимает запись в разделяемую часть памяти для распространения, мы используем Atomics - способ удостоверится, что при чтении значения, любой вид операции записи завершен.

Любая более подробная информация может быть найдена в предложении спецификации.

Website, name & logo
Copyright © 2022. Alex Myzgin