- Заполнения строки
- Object.values()
- Object.entries()
- getOwnPropertyDescriptors()
- «Висячие» запятые
- async/await или асинхронные функции
- Разделяемая память и атомарные операции
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 - способ удостоверится, что при чтении значения, любой вид операции записи завершен.
Любая более подробная информация может быть найдена в предложении спецификации.