ECMAScript 2015, 2016, 2017, 2018, 2019, 2020, 2021

от автора

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

ES3, ES5, ES6, ES7, ES8, ES2015, ES2016, ES2017, ES2018, ES2019, ECMAScript 2015, ECMAScript 2016, ECMAScript 2017, ECMAScript 2018, ECMAScript 2019 — как разобраться во всем этом?

ECMAScript (/ˈɛkməskrɪpt/) (или ES) является языком программирования общего назначения , стандартизирован ассоциацией Ecma International согласно документу ECMA-262 . Это стандарт JavaScript, предназначенный для обеспечения взаимодействия веб-страниц в разных веб-браузерах.

Историческая справка

Ecma International — основанная в 1961 году ассоциация, деятельность которой посвящена стандартизации информационных и коммуникационных технологий. Изначально ассоциация называлась ECMA — European Computer Manufacturers Association, однако она сменила название в 1994 году в связи с глобализацией деятельности. Вследствие этого название Ecma перестало быть аббревиатурой и больше не пишется заглавными буквами.

Когда JavaScript был создан, он был представлен Netscape и Sun Microsystems для Ecma, и они дали ему имя ECMA-262 (псевдоним ECMAScript).

До ES2015 спецификации ECMAScript обычно назывались их редакцией. Таким образом, ES5 является официальным названием обновления спецификации ECMAScript, опубликованной в 2009 году.

В процессе разработки ES2015, название было изменено с ES6 на ES2015, но мир всё еще называет релизы ES номером издания.

Также комитетом было принято решение о ежегодном пересмотре и выпуске стандарта, в результате, начиная с 2015 года, мы каждый год получаем новый стандарт ECMAScript.

Для лучшего понимания исторической последовательности развития стандартов JavaScript смотрите табличку ниже:

Даты релиза различных версий JavaScript

Даты релиза различных версий JavaScript

ECMAScript2015 (ES6)

ES5 разрабатывался 10 лет, с 1999 по 2009 год и был полон существенных изменений, поэтому он считает фундаментальной версией стандарта ECMAScript.

  • Стрелочные функции let func = (arg1, arg2, arg3) => expression

  • Более интуитивное управление текущим контекстом объекта this

  • Объявление переменных с помощью let и const

  • Промисы (Promises)

const waitFunc = () =>    new Promise((resolve, reject) => {      setTimeout(resolve, 1000);     });  waitFunc().then(() => {       console.log("I promised to run after 1s");   });
  • Генераторы (Generators)— это особый тип функций, которые могут приостанавливать своё выполнение, возвращать промежуточный результат и далее возобновлять его позже, в произвольный момент времени, что позволяет запускать другой код в момент приостановления функции. Для объявления генератора используется синтаксическая конструкция: function* (функция со звёздочкой).

  • Шаблонные литералы (Template Literals) — это новый синтаксис для создания строк, обеспечивающий способ встраивания выражений в строки, используя синтаксис ${имя_переменной}:

const name = "Irina"; const string = `Hey ${name}`; // Hey Irina
  • Параметры по умолчанию в функциях:

const sayMyName = function (name = "Irina") {     console.log(name); }; sayMyName(); // Irina
  • Spread/Rest синтаксис (...) в параметрах функций:

// spread Math.max(...[2,100,1,6,43]) // 100  // rest function print(format, ...params) {        console.log('params: ', params);        console.log('format: ', format);  }    print('hello', 'adrian', 321, Math.PI);
  • Деструктуризация (Destructuring Assignment) — синтаксис, позволяющий извлекать данные из массивов и объектов.

const user = {firstName: 'Adrian', lastName: 'Mejia'};    function getFullName({ firstName, lastName }) {         return `${firstName} ${lastName}`;  }   console.log(getFullName(user));
  • Symbol — это уникальный и неизменяемый тип данных, который может быть использован как идентификатор для свойств объектов.

var sym1 = Symbol(); var sym2 = Symbol("foo");  Symbol("foo") === Symbol("foo"); // false
  • Цикл for...of выполняет цикл обхода любых итерируемых объектов (включая ArrayMapSet, объект аргументов и т.д.), и имеет возможность разрыва break;

Итерируемым объектом является любой объект, который реализует интерфейс Iterable, то есть у которого есть метод Symbol.iterator, возвращающий объект с методом next().

  • Map и Set (и их соответствующие аналоги WeakMap и WeakSet с поддержкой сборки мусора) — являются официальными реализациями двух очень популярных структур данных:

Map содержит пары ключ-значение и сохраняет порядок вставки. Любое значение может быть использовано в качестве ключа.

Set позволяет сохранять уникальные значения любого типа.

Классы:

  • Конструктор — специальный метод constructor, который вызывается, когда класс инициализируются с помощью new. Родительский constructor наследуется автоматически, если у потомка нет своего метода constructor. Если же потомок имеет свой constructor, то, чтобы унаследовать конструктор родителя нужно использовать super() с аргументами для родителя.

  • super() — используется для вызова функций, принадлежащих родителю объекта;

  • Getters and setters:

get связывает свойство объекта с функцией, которая вызывается при обращении к этому свойству

class Person {     get fullName() {        return `${this.firstName} ${this.lastName}`;     } }

set связывает свойство объекта с функцией, он будет вызываться при попытке установить это свойство

class Person {     set age(years) {         this.theAge = years;     } }

Модули:

  • Импорт модулей

import defaultExport from "module-name"; import * as name from "module-name"; import * from 'module-name'; import { namedExport } from 'module-name'; import "module-name";
  • Экспорт модулей

export { name1, name2, …, nameN }; export default выражение; export * from …; export default function (…) { … };

Расширенные литералы объекта:

  • Более простой синтаксис для переменных, если они имеют одинаковые имена:

// вместо этого: const name = "Irina"; const x = {     name: name, };  // можно писать так: const name = "Irina"; const x = {     name, };
  • super()

const person = { name: "Irina", say: () => "Hello " }; const developer = {     __proto__: person,     say() {         return super.say() + this.name;    }, };  developer.say(); // Hello Irina
  • Динамические имена свойств объектов:

const myObj = {     ["some" + "thing"]: "123", };  myObj.something; // 123

Новые строковые методы:

  • repeat() повторяет строку указанное количество раз;

  • codePointAt() возвращает не отрицательное целое число, которое является закодированным в UTF-16 значением кодовой точки.

Новые методы объекта:

  • Object.is() определяет, являются ли два значения одинаковыми var isSame = Object.is(value1, value2);

  • Object.assign() используется для поверхностного копирования всех свойств объекта в целевой объект Object.assign(target, ...sources);

  • Object.setPrototypeOf устанавливает прототип объекта Object.setPrototypeOf(obj, prototype).

ECMAScript2016 (ES7)

Cодержит всего две функции:

  • Array.prototype.includes() — проверяет, содержит ли массив элемент, возвращая в зависимости от этого true или false.

  • Оператор возведения в степень ** — является эквивалентом Math.pow()

ECMAScript2017 (ES8)

  • String.prototype.padStart() и String.prototype.padEnd() — позволяют присоединять к строкам, в их начало или конец, некоторое количество символов для дополнения строк до заданной длины. Это полезно, если нужно выровнять текст, например, при выводе в консоль.

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

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

  • getOwnPropertyDescriptors() — принимает объект и возвращает все собственные дескрипторы свойств данного объекта (включая данные о геттерах и сеттерах).

  • «Висячие» запятые в параметрах функций — позволяет ставить запятую после последнего параметра функции.

const someFunc = (var1, var2,) => {     //... };  someFunc("test2", "test2",);
  • async/await или асинхронные функции — абстракция более высокого уровня по сравнению с промисами. Асинхронные функции позволяют избавиться от так называемого «ада коллбэков» и улучшить внешний вид и читаемость кода.

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

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

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

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

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

Более подробно об этом можно почитать в статье

ECMAScript2018 (ES9)

  • Асинхронная итерация for-await-of — позволяет вызывать асинхронные функции, которые возвращают промис (или массив с кучей промисов) в цикле:

const promises = [     new Promise(resolve => resolve(1)),     new Promise(resolve => resolve(2)),     new Promise(resolve => resolve(3))];  async function testFunc() {     for await (const obj of promises) {         console.log(obj);     } }  testFunc(); // 1, 2, 3
  • Promise.prototype.finally() — позволяет запускать код, независимо от успешного или неуспешного выполнения промиса:

fetch(myRequest)     .then(res => res.json())     .catch(error => console.error(error))     .finally(() => console.log("finished"));

Spread/Rest операторы для свойств объекта:

  • spread — позволяет создавать новый объект путем объединения свойств объекта, переданного после оператора ...:

const arr = { first, second, ...others }; arr; //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 }
  • rest — cинтаксис для rest оператора выглядит таким же как и для spread оператора, однако он используется для деструктуризации массивов и объектов. Фактически, rest оператор противоположен spread оператору: последний раскладывает массив на элементы, тогда как первый собирает много элементов в один.

const { first, second, ...others } = {     first: 1,     second: 2,     third: 3,    fourth: 4,     fifth: 5};  first; // 1 second; // 2 others; // { third: 3, fourth: 4, fifth: 5 }

Улучшения регулярных выражений:

  • Ретроспективные проверки (Lookbehind Assertion)

Позитивная ретроспективная проверка: (?<=Y)X, ищет совпадение с X при условии, что перед ним ЕСТЬ Y.

Негативная ретроспективная проверка: (?<!Y)X, ищет совпадение с X при условии, что перед ним НЕТ Y.

  • Юникодные свойства \p{…}

Несмотря на то, что это часть стандарта с 2018 года, юникодные свойства не поддерживаются в Firefox до 78 версии и в Edge до 79 версии.

Каждому символу в кодировке Юникод соответствует множество свойств, описывающих к какой «категории» относится символ и содержащих различную информацию о нём.

Например, свойство Letter у символа означает, что это буква какого-то алфавита, причём любого. А свойство Number означает, что это цифра – арабская или китайская, и т.п, на каком-то из языков.

В регулярном выражении можно искать символ с заданным свойством, указав его в \p{…}.

Например, \p{Letter} обозначает букву в любом языке. Также можно использовать запись \p{L}, так как L – это псевдоним Letter. Существуют короткие записи почти для всех свойств.

Несмотря на то, что это часть стандарта с 2018 года, юникодные свойства не поддерживаются в Firefox до 78 версии и в Edge до 79 версии.

Существует библиотека XRegExp, которая реализует «расширенные» регулярные выражения с кросс-браузерной поддержкой юникодных свойств.

В сложных регулярных выражениях запоминать группы по номерам затруднительно. Гораздо лучше — давать скобкам имена. Это делается добавлением ?<name> непосредственно после открытия скобки.

Например, поищем дату в формате «день-месяц-год»:

let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/; let str = "2021-03-30"; let groups = str.match(dateRegexp).groups; alert(groups.year); // 2021 alert(groups.month); // 03 alert(groups.day); // 30
  • Флаг s — включает режим «dotall», при котором точка . может соответствовать символу перевода строки \n

ECMAScript2019 (ES10)

  • Array.flat() — возвращает новый массив, в котором все элементы вложенных подмассивов были рекурсивно “подняты” на указанный уровень глубины (depth).

Вызов flat() без каких-либо аргументов сглаживает только первый уровень глубины. Можно указать необязательный аргумент глубины или вызвать функцию последовательно.

var arr1 = [1, 2, [3, 4]]; arr1.flat(); // [1, 2, 3, 4]  var arr2 = [1, 2, [3, 4, [5, 6]]]; arr2.flat(); // [1, 2, 3, 4, [5, 6]]  var arr3 = [1, 2, [3, 4, [5, 6]]]; arr3.flat(2); // [1, 2, 3, 4, 5, 6]  var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • Array.flatMap() — сначала применяет функцию к каждому элементу, а затем преобразует полученный результат в плоскую структуру и помещает в новый массив. Это идентично map функции, с последующим применением функции flat с параметром depth равным 1, но flatMap часто бывает полезным, так как работает немного более эффективно.

  • String.trimStart() и String.trimEnd() — удаляют пробелы в начале и в конце строки соответственно.

  • Необязательная привязка catch — позволяет разработчикам использовать try/catch без параметра error внутри блока catch.

  • Object.fromEntries() — создает объект или преобразует пары ключ-значение в объект. Он принимает только итерируемый объект: Object.fromEntries(iterable).

  • Symbol.description — read-only cвойство — строка, возвращающая необязательное описание объектов Symbol

console.log(Symbol('desc').description); // expected output: "desc"
  • Хорошо сформированный JSON.stringify()

Исправленный вывод JSON.stringify() при обработке суррогатных кодовых точек UTF-8 (от U+D800 до U+DFFF).

Перед этим изменением вызов JSON.stringify() возвращал некорректный символ Unicode («�»).

Теперь эти суррогатные кодовые точки можно безопасно представить в виде строк, используя JSON.stringify(), и преобразовать обратно в их исходное представление, используя JSON.parse().

JSON.stringify('\uD800'); > '"�"'  JSON.stringify('\uD800'); > '"\\ud800"' 
  • Корректировки метода Function.prototype.toString()

Функции всегда имели метод экземпляра toString(), который возвращает строку, содержащую код функции.

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

Например, для функции:

function /* a comment */ name() {}  // Поведение было таким: name.toString(); // "function name() {}"  // Стало таким: name.toString(); // "function /* a comment */ name () {}"

ECMAScript2020 (ES11)

  • String.matchAll — возвращает итератор, который в свою очередь возвращает все совпадающие группы одну за другой.

const str = "abc"; const regexp = /[a-c]/g; const iterator = str.matchAll(regexp);  for (result of iterator) {     console.log(result); } // ["a", index: 0, input: "abc", groups: undefined] // ["b", index: 1, input: "abc", groups: undefined] // ["c", index: 2, input: "abc", groups: undefined]
  • Динамический импорт — даёт возможность динамически импортировать файлы JS в виде модулей.

let modulePath = prompt("Какой модуль загружать?");  import(modulePath)    .then(obj => <объект модуля>)    .catch(err => <ошибка загрузки, например если нет такого модуля>)
  • BigInt — это специальный числовой тип, который предоставляет возможность работать с целыми числами произвольной длины.

Т.е. это способ представлять целые числа больше pow(2, 53) - 1, максимального числа, которое JavaScript может надежно представить с Number примитивом.

Чтобы создать значение типа BigInt, необходимо добавить n в конец числового литерала или вызвать функцию BigInt, которая создаст число типа BigInt из переданного аргумента. Аргументом может быть число, строка и др.

const bigint = 1234567890123456789012345678901234567890n;    const sameBigint = BigInt("1234567890123456789012345678901234567890");    const bigintFromNumber = BigInt(10); // то же самое, что и 10n
  • Promise.allSettled — возвращает промис, который исполняется когда все полученные промисы завершены (выполнены успешно или отклонены), содержащий массив результатов исполнения полученных промисов.

  • globalThis

В JavaScript всегда есть один большой объект контекста, который содержит всё. Традиционно в браузерах это window. Но если попытаться получить к нему доступ в Node, то будет ошибка. В Node нет глобального объекта window — вместо этого есть объект global. С другой стороны, в WebWorkers нет доступа к window, но вместо этого есть self.

globalThis всегда ссылается на глобальный объект, независимо от того, где мы выполняем свой код.

  • for-in mechanics — стандарт в каком порядке цикл for (x in y) должен выполняться.

  • Optional chaining — Оператор опциональной последовательности(?.)

Призван сделать код короче, при работе со вложенными объектами и проверкой на undefined.

const car = {}; const color = car?.color; const colorName = car?.color?.name;
  • Nullish coalescing — Оператор нулевого слияния (??)

Возвращает значение правого операнда когда значение левого операнда равно null или undefined, в противном случае будет возвращено значение левого операнда.

const foo = null ?? 'default string'; console.log(foo); // expected output: "default string"  const baz = 0 ?? 42; console.log(baz); // expected output: 0
  • Module namespace exports

export * as utils from "./utils.mjs";  // эквивалентно следующему: import * as utils from "./utils.mjs"; export { utils };

ECMAScript2021 (ES12)

P.S. Данный материал был написан в начале 2021 года, для просмотра актуальной информации читайте вторую часть моей статьи 🙂

Ожидается, что версия ECMAScript 2021 будет выпущена в июне 2021 года. Вот некоторые из функций, которые могут оказаться в ES2021 (ES12). Список подготовлен на основе ECMAScript Proposals и новых функций, выпущенных движком Google Chrome V8.

Все функции, перечисленные ниже, на момент написания поддерживаются в сборке Google Chrome Canary (версия браузера Google Chrome, поддерживающая экспериментальные возможности).

  • String.prototype.replaceAll() заменяет все вхождения строки другим строковым значением.

  • Приватные методы — могут быть доступны только внутри класса, в котором они определены. Имена приватных методов начинаются с символа #.

class Person {               #setType() {                 console.log("I am Private");         }                show() {                 this.#setType();         }  }    const personObj = new Person();  personObj.show(); // "I am Private";  personObj.setType(); // TypeError: personObj.setType is not a function
  • Приватные аксессоры

class Person {           get name() { return "Backbencher" }         set name(value) {}                get #age() { return 42 }          set #age(value) {}  }  const obj = new Person();  console.log(obj.name); // "Backbencher" console.log(obj.age); // undefined
  • WeakRef — слабые ссылки (Weak References). В основном слабые ссылки используются для реализации кэшей или маппингов больших объектов. В таких сценариях мы не хотим удерживать большое количество памяти надолго, сохраняя редко используемый кэш или маппинг. Мы можем разрешить сборку мусора для памяти в ближайшее время, а позже, если она нам снова понадобится, мы можем создать свежий кэш.

  • Финализаторы (FinalizationRegistry)—это дополнительная функция WeakRefпозволяющая регистрировать коллбеки, которые будут вызываться после того, как объект был забран сборщиком мусора.

  • Promise.any() — успешно завершается, если успешно завершился любой из предоставленных в качестве аргументов промис.

Если ни один из промисов не завершится успешно Promise.any() сгенерирует исключение AggregateError. Нам нужно поймать это исключение и обработать.

  • Оператор логического присваивания (&&= ,||= ,??=) — объединяет логические операции (&& , || или??) с присваиванием.

const x = 1;   const y = 2;  const z;  x &&= y;  // 2 x ||= y;  // 1 z ??= y;  // 2

При написании статьи использованы следующие ресурсы:

  1. Официальный сайт ecma-international

  2. Справочник по JavaScript

  3. Полное руководство по ECMAScript

  4. Обзор новшеств ECMAScript 2016, 2017, и 2018 с примерами

  5. Что нового в JavaScript ES2019

  6. Нововведения JavaScript ES2020 с простыми примерами

  7. Новые возможности ES2021 / ES12


ссылка на оригинал статьи https://habr.com/ru/articles/740934/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *