В общем-то, тема новшеств в EcmaScript постоянно на слуху. Это далеко не случайно, так как новые стандарты, с некоторых пор, выходят ежегодно. Стандарт ES6 появился в 2015-м, ES7 — в 2016-м. Но вряд ли кто сразу вспомнит, когда вышел ES5, так как случилось это в 2009-м году, до эпохи бурного роста и развития JavaScript. Пожалуй, каждый JS-разработчик наблюдает за развитием языка. Сегодня пришло время поговорить о том, что принёс нам ES8.
Если вы не ищете лёгких путей — можете сразу перейти к веб-версии или к PDF-варианту нового стандарта. Кроме того, полезные сведения о возможностях ES8 можно найти на сайте MDN, материалы которого использовались и при подготовке этого обзора. Тех же, кто хочет быстро ознакомиться с основными нововведениями ES8 и взглянуть на примеры кода, приглашаем под кат.
Дополнение строк до заданной длины
Эта возможность реализована с помощью двух методов объекта String
: padStart()
и padEnd()
. Слова «Начало» и «Конец» в названиях функций намекают на их роли в деле обработки строк. А именно, они позволяют задавать параметры дополнения строк до достижения ими заданной длины. Метод padStart()
дополняет строку с её начала (слева), padEnd()
— с конца (справа). Строки можно дополнять заданными одиночными символами, другими строками, или, по умолчанию, пробелами. Вот синтаксис функций, о которых идёт речь:
str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
Как видите, первый параметр этих функций — targetLength
. Он представляет собой целевую длину результирующей строки. Второй параметр, необязательный padString
, это строка, которой будет дополняться исходная строка. Без указания этого параметра для дополнения будет использоваться пробел. Если длина строки, к которой применяется один из этих методов, превышает заданную, исходная строка остаётся неизменной.
Вот несколько примеров:
'es8'.padStart(2); // 'es8'
'es8'.padStart(5); // ' es8'
'es8'.padStart(6, 'woof'); // 'wooes8'
'es8'.padStart(14, 'wow'); // 'wowwowwowwoes8'
'es8'.padStart(7, '0'); // '0000es8'
'es8'.padEnd(2); // 'es8'
'es8'.padEnd(5); // 'es8 '
'es8'.padEnd(6, 'woof'); // 'es8woo'
'es8'.padEnd(14, 'wow'); // 'es8wowwowwowwo'
'es8'.padEnd(7, '6'); // 'es86666'
Поддержка в браузерах (MDN)
Методы Object.values() и Object.entries()
Метод Object.values()
возвращает массив собственных перечисляемых свойств переданного ему объекта в том же порядке, в котором это делает цикл for…in
. Синтаксис метода предельно прост:
Object.values(obj)
Параметр obj
— это тот объект, свойства которого надо получить. Он может быть объектом или массивом (иными словами, объектом с индексами наподобие [10, 20, 30] -> { 0: 10, 1: 20, 2: 30 }
). Вот пример кода:
const obj = { x: 'xxx', y: 1 };
Object.values(obj); // ['xxx', 1]
const obj = ['e', 's', '8']; // то же самое, что и { 0: 'e', 1: 's', 2: '8' };
Object.values(obj); // ['e', 's', '8']
Поддержка Object.values() в браузерах (MDN)
Метод Object.entries()
возвращает массив собственных перечисляемых свойств объекта в формате [ключ, значение]
, в том же порядке, что и Object.values()
. Синтаксис метода аналогичен Object.values()
, да и в остальном эти методы похожи:
Object.entries(obj)
Вот примеры:
const obj = { x: 'xxx', y: 1 };
Object.entries(obj); // [['x', 'xxx'], ['y', 1]]
const obj = ['e', 's', '8'];
Object.entries(obj); // [['0', 'e'], ['1', 's'], ['2', '8']]
const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]
Object.entries('es8'); // [['0', 'e'], ['1', 's'], ['2', '8']]
Поддержка Object.entries() в браузерах (MDN)
Метод Object.getOwnPropertyDescriptors()
Метод Object.getOwnPropertyDescriptors()
возвращает дескриптор собственного свойства переданного объекта. Собственное свойство определено непосредственно в объекте, а не получено через цепочку прототипов. Вот синтаксис метода:
Object.getOwnPropertyDescriptor(obj, prop)
Аргумент obj
— это объект, данные по свойству которого надо получить, аргумент prop
— это имя свойства, дескриптор которого нас интересует. В результате успешного выполнения этого метода будет возвращён объект, в котором могут быть следующие ключи:
configurable — true
— если тип дескриптора свойства может быть изменён и если свойство может быть удалено из содержащего его объекта, иначеfalse
.enumerable
—true
— если свойство доступно при перечислении свойств объекта, иначе —false
.writable
—true
— если значение ассоциированное со свойством, может быть изменено, иначеfalse
(для дескрипторов данных)get
— функция, возвращающая значение свойства, либо, если она отсутствует —undefined
(для дескрипторов доступа)set
— функция, изменяющая значение свойства, либо, если она отсутствует —undefined
(для дескрипторов доступа)value
— значение, ассоциированное со свойством (для дескрипторов данных).
Вот пример кода:
const obj = { get es8() { return 888; } };
Object.getOwnPropertyDescriptor(obj, 'es8');
// {
// configurable: true,
// enumerable: true,
// get: function es8(){}, //функция-геттер
// set: undefined
// }
Дескрипторы данных весьма важны для таких механизмов языка, как декораторы.
Поддержка браузерами (MDN)
Завершающие запятые в параметрах функций
Использование завершающих запятых способно упростить редактирование кода и облегчить работу с системами контроля версий. Подобная возможность уже присутствовала в языке для литералов массивов (с самого начала) и объектов (начиная с ES5). Например: [10, 20, 30,]
и { x: 1, }
.
Теперь завершающие запятые поддерживаются в списках параметров функций. Раньше появление запятой в конце списка параметров вызывало ошибку SyntaxError
. Теперь же этого не происходит. Вот пример объявления функции, в списке параметров которой есть завершающая запятая:
function es8(var1, var2, var3,) {
// ...
}
Завершающая запятая может появиться и при вызове функции:
es8(10, 20, 30,);
Асинхронные функции
Ключевое слово async
позволяет определить асинхронную функцию, которая возвращает объект AsyncFunction. Внутри их работа во многом похожа на то, как работают генераторы.
Вот пример кода:
function fetchTextByPromise() {
return new Promise(resolve => {
setTimeout(() => {
resolve("es8");
}, 2000));
});
}
async function sayHello() {
const externalFetchedText = await fetchTextByPromise();
console.log(`Hello, ${externalFetchedText}`); // Hello, es8
}
sayHello();
Вызов sayHello()
приведёт к выводу в лог строки «Hello, es8
» с задержкой в 2 секунды, при этом главный поток выполнения не блокируется. Вот как это выглядит:
console.log(1);
sayHello();
console.log(2);
В консоли, после выполнения этого кода, появится следующее:
1 // немедленно
2 // немедленно
Hello, es8 // через 2 секунды
Как видно, два вызова console.log()
выполняются один за другим, а асинхронная функция, не блокируя главный поток, выполняется через 2 секунды.
Обратите внимание на то, что асинхронные функции всегда возвращают промисы, и ключевое слово await
можно использовать только в функциях, определённых с использованием ключевого слова async
.
Поддержка браузерами (MDN)
Разделяемая память и объект Atomics
Если несколько потоков пользуются общей памятью, они могут одновременно писать в неё данные и читать данные из неё. Атомарные операции позволяют обеспечить целостность данных и предсказуемость результатов выполнения операций. То есть, например, гарантировать то, что некая операция завершится до того, как начнётся другая, или то, что некая операция не будет прервана. Подобную функциональность в ES8 обеспечивают новые механизмы языка. Во-первых — это объект SharedArrayBuffer, во-вторых, объект Atomics, содержащий набор статических методов.
Объект Atomics
нельзя использовать как конструктор, он, в этом плане, похож на Math
. Существуют методы объекта Atomics
, которые позволяют выполнять различные безопасные операции с элементами типизированных массивов, служащих для доступа к объектам SharedArrayBuffer
. Среди них, например, метод Atomics.add()
для прибавления указанного числа к тому, что хранится в заданной позиции массива. Есть в Atomics
и методы для организации управления блокировками, в частности, это Atomics.wait()
и Atomics.wake()
.
Поддержка браузерами (MDN)
Заглянем в будущее: расширение возможностей тегированных шаблонных строк в ES9
В ES6 появились тегированные шаблонные строки. Вывод таких шаблонов можно изменять с помощью функций, подчиняя его некоей необходимой нам логике. Например:
const esth = 8;
helper`ES ${esth} is `;
function helper(strs, ...keys) {
const str1 = strs[0]; // ES
const str2 = strs[1]; // is
let additionalPart = '';
if (keys[0] == 8) { // 8
additionalPart = 'awesome';
}
else {
additionalPart = 'good';
}
return `${str1} ${keys[0]} ${str2} ${additionalPart}.`;
}
Если в esth
записано число 8
, функция возвратит «ES 8 is awesome
». Если же в esth
будет 7
, то функция вернёт «ES 7 is good
».
Однако, до сих пор на тегированные шаблоны накладываются некоторые ограничения. Они связаны с escape-последовательностями. Например, это касается подстрок, начинающихся на u
или x
. В частности, например, после u
должен следовать код символа Unicode, иначе появится сообщение об ошибке. Ожидается, что в ES9 это ограничение будет снято.
Поддержка браузерами (MDN)
Итоги
JavaScript — это язык, который используется в неисчислимом множестве работающих веб-проектов, и он, при этом, постоянно обновляется. Процесс этот отлично организованный и сбалансированный. На последней стадии принятия новшеств, их одобряет комитет TC39, после чего их реализуют разработчики JS-движков. Надо сказать, что большинство нововведений ES8 уже поддерживает TypeScript, их поддерживают многие браузеры, в некоторых случаях помогают полифиллы, поэтому новые возможности JavaScript можно пустить в дело прямо сейчас.
Уважаемые читатели! Пользуетесь ли вы новшествами ES8?
Автор: ru_vds