- PVSM.RU - https://www.pvsm.ru -

EcmaScript 10 — JavaScript в этом году

Стандартизация JS перешла на годичный цикл обновлений, а начало года — отличное время для того чтобы узнать, что нас ждёт в юбилейной — уже десятой редакции EcmaScript!

ES9 — актуальная версия спецификации [1].

ES10 — всё ещё черновик [2].

На сегодняшний день в Stage 4 # [3] — всего несколько предложений.

А в Stage 3 # [4] — целая дюжина!

Из них, на мой взгляд, самые интересные — приватные поля классов # [5], шебанг грамматика для скриптов # [6], числа произвольной точности # [7], доступ к глобальному контексту # [8] и динамические импорты # [9].

 
КДПВ: Жёлтый магнит с надписью «JS ES10» на экране монитора —  от kasper.green & elfafeya.art
        Автор фото: kasper.green; Жёлтый магнит: elfafeya.art & kasper.green

Содержание

Пять стадий # [10]

Stage 4 — Final # [11]

•      catch — аргумент стал необязательным # [12];

•      Symbol().description — акцессор к описанию символа # [13];

•      'строки EcmaScript' — улучшенная совместимость с JSON форматом # [14];

•      .toString() — прототипный метод обновлён # [15].


Stage 3 — Pre-release # [16]

•      # — приватное всё у классов, через октоторп # [17];

•      #!/usr/bin/env node — шебанг грамматика для скриптов # [18];

•      BigInt() — новый примитив, для чисел произвольной точности # [19];

•      globalThis — новый способ доступа к глобальному контексту # [20];

•      import(dynamic) — динамический импорт # [21];

•      import.meta — мета-информация о загружаемом модуле # [22];

•      Object.fromEntries() — создание объекта из массива пар — ключзначение # [23];

•      JSON.stringify() — фикс метода # [24];

•      RegExp — устаревшие возможности # [25];

•      .trimStart() и .trimEnd() — прототипные методы строк # [26];

•      .matchAll().match() с глобальным флагом # [27];

•      .flat() и .flatMap() — прототипные методы массивов # [28].

Итоги # [29]


Пять стадий

   Stage 0   ↓   Strawman  Наметка           Идея, которую можно реализовать через Babel-плагин.;

   Stage 1   ↓   Proposal  Предложение     Проверка жизнеспособности идеи.;

   Stage 2   ↓   Draft  Черновик                  Начало разработки спецификации.;

   Stage 3   ↓   Candidate  Кандидат         Предварительная версия спецификации.;

   Stage 4  ֍  Finished  Завершён           Финальная версия спецификации на этот год.


Мы рассмотрим только Stage 4 — де-факто, вошедший в стандарт.

И Stage 3 — который вот-вот станет его частью.


 

֍ Stage 4

Эти изменения уже вошли в стандарт.

Необязательный аргумент у catch

https://github.com/tc39/proposal-optional-catch-binding [30]

До ES10 блок catch требовал обязательного аргумента для сбора информации об ошибке, даже если она не используется:

function isValidJSON(text) {
  try {
    JSON.parse(text);
    return true;
  } catch(unusedVariable) { // переменная не используется
    return false;
  }
}

EcmaScript 10 — JavaScript в этом году - 2
Edge пока не обновлён до ES10, и ожидаемо валится с ошибкой

Начиная с редакции ES10, круглые скобки можно опустить и catch станет как две капли воды похож на try.

EcmaScript 10 — JavaScript в этом году - 3
Мой Chrome уже обновился до ES10, а местами и до Stage 3. Дальше скриншоты будут из Chrome

исходный код

function isValidJSON(text) {
  try {
    JSON.parse(text);
    return true;
  } catch { // без аргумента
    return false;
  }
}

 
 

Доступ к описанию символьной ссылки

https://tc39.github.io/proposal-Symbol-description/ [31]

Описание символьной ссылки можно косвенно получить методом toString():

const symbol_link = Symbol("Symbol description")
String(symbol_link) // "Symbol(Symbol description)"

Начиная с ES10 у символов появилось свойство description, доступное только для чтения. Оно позволяет без всяких танцев с бубном получить описание символа:

symbol_link.description
// "Symbol description"

В случае если описание не задано, вернётся — undefined:

const without_description_symbol_link = Symbol()
without_description_symbol_link.description
// undefined

const empty_description_symbol_link = Symbol('')
empty_description_symbol_link.description
// ""

 
 

Строки EcmaScript совместимые с JSON

https://github.com/tc39/proposal-json-superset [32]

EcmaScript до десятой редакции утверждает, что JSON является подмножеством JSON.parse, но это неверно.

JSON строки могут содержать неэкранированные символы разделителей линий U+2028 LINE SEPARATOR и абзацев U+2029 PARAGRAPH SEPARATOR.

Строки ECMAScript до десятой версии — нет.

Если в Edge вызвать eval() со строкой "u2029",
он ведёт себя так, словно мы сделали перенос строки — прямо посреди кода:

EcmaScript 10 — JavaScript в этом году - 4

 

C ES10 строками — всё в порядке:

EcmaScript 10 — JavaScript в этом году - 5

 
 

Доработка прототипного метода .toString()

http://tc39.github.io/Function-prototype-toString-revision/ [33]

Цели изменений

  • убрать обратно несовместимое требование:

Если реализация не может создать строку исходного кода, соответствующую этим критериям, она должна вернуть строку, для которой eval будет выброшено исключение с ошибкой синтаксиса.

  • уточнить «функционально эквивалентное» требование;

  • стандартизировать строковое представление встроенных функций и хост-объектов;

  • уточнить требования к представлению на основе «фактических характеристик» объекта;

  • убедиться, что синтаксический анализ строки содержит то же тело функции и список параметров, что и оригинал;

  • для функций, определенных с использованием кода ECMAScript, toString должен возвращать фрагмент исходного текста от начала первого токена до конца последнего токена, соответствующего соответствующей грамматической конструкции;

  • для встроенных функциональных объектов toStringне должны возвращать ничего, кроме NativeFunction;

  • для вызываемых объектов, которые не были определены с использованием кода ECMAScript, toString необходимо вернуть NativeFunction;

  • для функций, создаваемых динамически (конструкторы функции или генератора) toString, должен синтезировать исходный текст;

  • для всех других объектов, toString должен бросить TypeError исключение.

// Пользовательская функция
function () { console.log('My Function!'); }.toString();
// function () { console.log('My Function!'); }

// Метод встроенного объекта объект
Number.parseInt.toString();
// function parseInt() { [native code] }

// Функция с привязкой контекста
function () { }.bind(0).toString();
// function () { [native code] }

// Встроенные вызываемые функциональный объекты
Symbol.toString();
// function Symbol() { [native code] }

// Динамически создаваемый функциональный объект
Function().toString();
// function anonymous() {}

// Динамически создаваемый функциональный объект-генератор
function* () { }.toString();
// function* () { }

// .call теперь обязательно ждёт, в качестве аргумента, функцию
Function.prototype.toString.call({});
// Function.prototype.toString requires that 'this' be a Function"


 
 

֍ Stage 3

Предложения вышедшие из статуса черновика, но ещё не вошедшие в финальную версию стандарта. 

Приватныестатическиепубличные методысвойстваатрибуты у классов

https://github.com/tc39/proposal-class-fields [34]
https://github.com/tc39/proposal-private-methods [35]
https://github.com/tc39/proposal-static-class-features [36]

В некоторых языках есть договорённость, называть приватные методы через видимый пробел ( «_» — такая_штука, ты можешь знать этот знак под неверным названием — нижнее подчёркивание).

Например так:

<?php
class AdultContent {
    private $_age = 0;
    private $_content = '…is dummy example content (•)(•) —3 (.)(.) only for adults…';
    function __construct($age) {
        $this->_age = $age;
    }
    function __get($name) {
        if($name === 'content') {
            return " (age: ".$this->_age.") → ".$this->_getContent()."rn";
        }
        else {
            return 'without info';
        }
    }
    private function _getContent() {
        if($this->_contentIsAllowed()) {
            return $this->_content;
        }
        return 'Sorry. Content not for you.';
    }
    private function _contentIsAllowed() {
        return $this->_age >= 18;
    }
    function __toString() {
        return $this->content;
    }
}
echo "<pre>";

echo strval(new AdultContent(10));
//  (age: 10) →  Sorry. Content not for you

echo strval(new AdultContent(25));
// (age: 25) →  …is dummy example content (•)(•) —3 only for adults…

$ObjectAdultContent = new AdultContent(32);
echo $ObjectAdultContent->content;
// (age: 32) →  …is dummy example content (•)(•) —3 only for adults…
?>

Напомню — это только договорённость. Ничто не мешает использовать префикс для других целей, использовать другой префикс, или не использовать вовсе.

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

Разработчики спецификации EcmaScript пошли дальше и сделали префикс-октоторп ( «#» —решётка, хеш ) частью синтаксиса.

Предыдущий пример на ES10 можно переписать следующим образом:

export default class AdultContent {

  // Приватные атрибуты класса
  #age = 0
  #adult_content = '…is dummy example content (•)(•) —3 (.)(.) only for adults…'

  constructor(age) {
    this.#setAge(age)
  }

  // Статический приватный метод
  static #userIsAdult(age) {
    return age > 18
  }

  // Публичное свойство
  get content () {
    return `(age: ${this.#age}) → ` + this.#allowed_content
  }

  // Приватное свойство
  get #allowed_content() {
      if(AdultContent.userIsAdult(this.age)){
        return this.#adult_content
    }
    else {
        return 'Sorry. Content not for you.'
    }
  }

  // Приватный метод
  #setAge(age) {
      this.#age = age
  }

  toString () {
    return this.#content
  }
}

const AdultContentForKid = new AdultContent(10)

console.log(String(AdultContentForKid))
// (age: 10) → Sorry. Content not for you.

console.log(AdultContentForKid.content)
// (age: 10) → Sorry. Content not for you.

const AdultContentForAdult = new AdultContent(25)

console.log(String(AdultContentForAdult))
// (age: 25) → …is dummy example content (•)(•) —3 (.)(.) only for adults…

console.log(AdultContentForAdult.content)
// (age: 25) → …is dummy example content (•)(•) —3 (.)(.) only for adults…

Пример излишне усложнён для демонстрации приватных свойств, методов и атрибутов разом. Но в целом JS — радует глаз своей лаконичностью по сравнению с PHP вариантом. Никаких тебе private function _..., ни точек с запятой в конце строки, и точка вместо «->» для перехода вглубь объекта.

Геттеры именованные. Для динамических имён — прокси-объекты.

Вроде бы мелочи, но после перехода на JS, всё меньше желания возвращаться к PHP.

К слову приватные акцессоры доступны только с Babel 7.3.0 и старше.

Крайняя версия на npmjs.com — 7.2.2

Ждём в Stage 4!

 
 

Шебанг грамматика

https://github.com/tc39/proposal-hashbang [37]

Хешбэнг — знакомый юниксойдам способ указать интерпретатор для исполняемого файла:

#!/usr/bin/env node
// в скрипте
'use strict';
console.log(1);

#!/usr/bin/env node
// в модуле
export {};
console.log(1);

в данный момент, на подобный фортель, Chrome выбрасывает SyntaxError: Invalid or&nbsp;unexpected token
 
 

Большие числа с BigInt

https://github.com/tc39/proposal-bigint [38]

работает в Chrome

Максимальное целое число, которое можно безопасно использовать в JavaScript (2⁵³ — 1):

console.log(Number.MAX_SAFE_INTEGER)
// 9007199254740991

BigInt нужен для использования чисел произвольной точности.

Объявляется этот тип несколькими способами:

// используя 'n' постфикс в конце более длинных чисел
910000000000000100500n
// 910000000000000100500n

// напрямую передав в конструктор примитива BigInt() без постфикса
BigInt( 910000000000000200500 )
// 910000000000000200500n

// или передав строку в тот-же конструктор
BigInt( "910000000000000300500" )
// 910000000000000300500n

// пример очень большого числа длиной 1642 знака
BigInt( "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" )
\ 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999n

Это новый примитивный тип:

typeof 123;
// → 'number'
typeof 123n;
// → 'bigint'

Его можно сравнивать с обычными числами:

42n === BigInt(42);
// → true
42n == 42;
// → true

Но математические операции нужно проводить в пределах одного типа:

20000000000000n/20n
// 1000000000000n

20000000000000n/20
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

Поддерживается унарный минус, унарный плюс возвращает ошибку:

 -2n
 // -2n

 +2n
 // Uncaught TypeError: Cannot convert a BigInt value to a number

 

globalThis — новый способ доступа к глобальному контексту

https://github.com/tc39/proposal-global [39]

работает в Chrome

Поскольку реализации глобальной области видимости зависят от конкретного движка, раньше приходилось делать что-то вроде этого:

var getGlobal = function () {
    if (typeof self !== 'undefined') { return self; }
    if (typeof window !== 'undefined') { return window; }
    if (typeof global !== 'undefined') { return global; }
    throw new Error('unable to locate global object');
};

И даже такой вариант не гарантировал, что всё точно будет работать.

globalThis — общий для всех платформ способ доступа к глобальной области видимости:

// Обращение к глобальному конструктору массива
globalThis.Array(1,2,3)
// [1, 2, 3]

// Запись собственных данных в глобальную область видимости
globalThis.myGLobalSettings = {
    it_is_cool: true
}

// Чтение собственных данных из глобальной области видимости
globalThis.myGLobalSettings
// {it_is_cool: true}

 
 

Динамический import(dynamic)

https://github.com/tc39/proposal-dynamic-import [40]

работает в Chrome

Хотелось переменные в строках импорта‽ С динамическими импортами это стало возможно:

import(`./language-packs/${navigator.language}.js`)

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

Поэтому загружать модули можно — отложенно, когда это необходимо:

element.addEventListener('click', async () => {
    // можно использовать await синтаксис для промиса
    const module = await import(`./events_scripts/supperButtonClickEvent.js`)
    module.clickEvent()
})

Синтаксически, это выглядит как вызов функции import(), но не наследуется от Function.prototype, а значит вызвать через call или apply — не удастся:

import.call("example this", "argument")
// Uncaught SyntaxError: Unexpected identifier

 
 

import.meta — мета-информация о загружаемом модуле.

https://github.com/tc39/proposal-import-meta [41]

работает в Chrome

В коде загружаемого модуля стало возможно получить информацию по нему. Сейчас это только адрес по которому модуль был загружен:

console.log(import.meta);
// { url: "file:///home/user/my-module.js" }

 
 

Создание объекта методом Object.fromEntries()

https://github.com/tc39/proposal-object-from-entries [42]

Аналог _.fromPairs из lodash:

Object.fromPairs([['key_1', 1], ['key_2', 2]])
// {key_1: 1; key_2: 2}

 
 

Фикс метода JSON.stringify()

https://github.com/tc39/proposal-well-formed-stringify [43]

В разделе 8.1 RFC 8259 [44] требуется, чтобы текст JSON, обмениваемый за пределами замкнутой экосистемы, кодировался с использованием UTF-8, но JSON.stringify может возвращать строки, содержащие кодовые точки, которые не представлены в UTF-8 (в частности, суррогатные кодовые точки от U+D800 до U+DFFF)

Так строка uDF06uD834 после обработки JSON.stringify() превращается в \udf06\ud834:

/* Непарные суррогатные единицы будут сериализованы с экранированием последовательностей */
JSON.stringify('uDF06uD834')
'"\udf06\ud834"'
JSON.stringify('uDEAD')
'"\udead"'

Такого быть не должно, и новая спецификация это исправляет. Edge и Chrome уже обновились.

 
 

Устаревшие возможности RegExp

https://github.com/tc39/proposal-regexp-legacy-features [45]

Спецификация для устаревших функций RegExp, вроде RegExp.$1, и RegExp.prototype.compile() метода.

 
 

Прототипные методы строк .trimStart() и .trimEnd()

https://github.com/tc39/proposal-string-left-right-trim [46]

работает в Chrome

По аналогии с методами .padStart() и .padEnd(), обрезают пробельные символы в начале и конце строки соответственно:

const one = "      hello and let ";
const two = "us begin.        ";
console.log( one.trimStart() + two.trimEnd() )
// "hello and let us begin."

 
 

.matchAll() — новый прототипный метод строк.

https://github.com/tc39/proposal-string-matchall [47]

работает в Chrome

Работает похоже на метод .match() с включенным флагом g, но возвращает итератор:

const string_for_searh = 'olololo'

// Вернёт первое вхождение с дополнительной информацией о нём
string_for_searh.match(/o/)
// ["o", index: 0, input: "olololo", groups: undefined]

//Вернёт массив всех вхождений без дополнительной информации
string_for_searh.match(/o/g)
// ["o", "o", "o", "o"]

// Вернёт итератор
string_for_searh.matchAll(/o/)
// {_r: /o/g, _s: "olololo"}

// Итератор возвращает каждое последующее вхождение с подробной информацией,
// как если бы мы использовали .match без глобального флага
for(const item of string_for_searh.matchAll(/o/)) {
  console.log(item)
}
// ["o", index: 0, input: "olololo", groups: undefined]
// ["o", index: 2, input: "olololo", groups: undefined]
// ["o", index: 4, input: "olololo", groups: undefined]
// ["o", index: 6, input: "olololo", groups: undefined]

Аргумент должен быть регулярным выражением, иначе будет выброшено исключение:

'olololo'.matchAll('o')
// Uncaught TypeError: o is not a regexp!

 
 

Одномерные массивы с .flat() и .flatMap()

https://github.com/tc39/proposal-flatMap [48]

работает в Chrome

Массив обзавёлся прототипами .flat() и .flatMap(), которые в целом похожи на реализации в lodash,
но всё же имеют некоторые отличия. Необязательный аргумент — устанавливает максимальную глубину обхода дерева:

const deep_deep_array = [
  '≥0 — первый уровень',
  [
    '≥1 — второй уровень',
    [
      '≥2 — третий уровень',
      [
        '≥3 — четвёртый уровень',
        [
          '≥4 — пятый уровень'
        ]
      ]
    ]
  ]
]

// 0 — вернёт массив без изменений
deep_deep_array.flat(0)
//  ["≥0 — первый уровень", Array(2)]

// 1 — глубина по умолчанию
deep_deep_array.flat()
//  ["первый уровень", "второй уровень", Array(2)]

deep_deep_array.flat(2)
//  ["первый уровень", "второй уровень", "третий уровень", Array(2)]

deep_deep_array.flat(100500)
// ["первый уровень", "второй уровень", "третий уровень", "четвёртый уровень", "пятый уровень"]

.flatMap() не эквивалентен последовательному вызову .flat().map(). Функция обратного вызова, передаваемая в метод, должна возвращать массив который станет частью общего плоского массива:

['Hello', 'World'].flatMap(word => [...word])
// ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"]

 


 
 

Итоги

Stage 4 привнёс скорее косметические изменения. Интерес представляет Stage 3. Большинство из предложений в Chrome уже реализованы, за исключением пожалуй Object.fromEntries(), наличие которого не критично, а приватные свойства очень ждём.

 


 

Исправления в статье

 
Если заметил в статье неточность, ошибку или есть чем дополнить — ты можешь написать мне личное сообщение [49], а лучше самому воспользоваться репозиторием статьи https://github.com/KasperGreen/es10 [50]

Материалы по теме

Актуальная версия стандарта Ecma-262 [1]

Черновик следующей версии стандарта Ecma-262 [2]

ECMAScript [51]

Новые #приватные поля классов в JavaScript [52]

Обзор возможностей стандартов ES7, ES8 и ES9 [53]

Шебанг [54]

BigInt — длинная арифметика в JavaScript [55]


 
 

Альтернативный вариант КДПВ с жёлтым магнитом от elfafeya.art
       Автор фото: kasper.green; Жёлтый магнит: elfafeya.art & kasper.green

Автор: KasperGreen

Источник [56]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/307238

Ссылки в тексте:

[1] актуальная версия спецификации: https://www.ecma-international.org/publications/standards/Ecma-262.htm

[2] черновик: https://tc39.github.io/ecma262/

[3] Stage 4 #: https://habr.com/ru/post/437806/#-stage-4

[4] Stage 3 #: https://habr.com/ru/post/437806/#-stage-3

[5] приватные поля классов #: https://habr.com/ru/post/437806/#privatnyestaticheskiepublichnye-metodysvoystvaatributy-u-klassov

[6] шебанг грамматика для скриптов #: https://habr.com/ru/post/437806/#shebang-grammatika

[7] числа произвольной точности #: https://habr.com/ru/post/437806/#bolshie-chisla-s-bigint

[8] доступ к глобальному контексту #: https://habr.com/ru/post/437806/#globalthis--novyy-sposob-dostupa-k-globalnomu-kontekstu

[9] динамические импорты #: https://habr.com/ru/post/437806/#dinamicheskiy-importdynamic

[10] Пять стадий #: #pyat-stadiy

[11] Stage 4 — Final #: #-stage-4

[12] catch — аргумент стал необязательным #: #neobyazatelnyy-argument-u-catch

[13] Symbol().description — акцессор к описанию символа #: #dostup-k-opisaniyu-simvolnoy-ssylki

[14] 'строки EcmaScript' — улучшенная совместимость с JSON форматом #: #stroki-ecmascript-sovmestimye-s-json

[15] .toString() — прототипный метод обновлён #: #dorabotka-prototipnogo-metoda-tostring

[16] Stage 3 — Pre-release #: #-stage-3

[17] # — приватное всё у классов, через октоторп #: #privatnyestaticheskiepublichnye-metodysvoystvaatributy-u-klassov

[18] #!/usr/bin/env node — шебанг грамматика для скриптов #: #shebang-grammatika

[19] BigInt() — новый примитив, для чисел произвольной точности #: #bolshie-chisla-s-bigint

[20] globalThis — новый способ доступа к глобальному контексту #: #globalthis--novyy-sposob-dostupa-k-globalnomu-kontekstu

[21] import(dynamic) — динамический импорт #: #dinamicheskiy-importdynamic

[22] import.meta — мета-информация о загружаемом модуле #: #importmeta--meta-informaciya-o-zagruzhaemom-module

[23] Object.fromEntries() — создание объекта из массива пар — ключзначение #: #sozdanie-obekta-metodom-objectfromentries

[24] JSON.stringify() — фикс метода #: #fiks-metoda-jsonstringify

[25] RegExp — устаревшие возможности #: #ustarevshie-vozmozhnosti-regexp

[26] .trimStart() и .trimEnd() — прототипные методы строк #: #prototipnye-metody-strok-trimstart-i-trimend

[27] .matchAll().match() с глобальным флагом #: #matchall--novyy-prototipnyy-metod-strok

[28] .flat() и .flatMap() — прототипные методы массивов #: #odnomernye-massivy-s-flat-i-flatmap

[29] Итоги #: #itogi

[30] https://github.com/tc39/proposal-optional-catch-binding: https://github.com/tc39/proposal-optional-catch-binding

[31] https://tc39.github.io/proposal-Symbol-description/: https://tc39.github.io/proposal-Symbol-description/

[32] https://github.com/tc39/proposal-json-superset: https://github.com/tc39/proposal-json-superset

[33] http://tc39.github.io/Function-prototype-toString-revision/: http://tc39.github.io/Function-prototype-toString-revision/

[34] https://github.com/tc39/proposal-class-fields: https://github.com/tc39/proposal-class-fields

[35] https://github.com/tc39/proposal-private-methods: https://github.com/tc39/proposal-private-methods

[36] https://github.com/tc39/proposal-static-class-features: https://github.com/tc39/proposal-static-class-features

[37] https://github.com/tc39/proposal-hashbang: https://github.com/tc39/proposal-hashbang

[38] https://github.com/tc39/proposal-bigint: https://github.com/tc39/proposal-bigint

[39] https://github.com/tc39/proposal-global: https://github.com/tc39/proposal-global

[40] https://github.com/tc39/proposal-dynamic-import: https://github.com/tc39/proposal-dynamic-import

[41] https://github.com/tc39/proposal-import-meta: https://github.com/tc39/proposal-import-meta

[42] https://github.com/tc39/proposal-object-from-entries: https://github.com/tc39/proposal-object-from-entries

[43] https://github.com/tc39/proposal-well-formed-stringify: https://github.com/tc39/proposal-well-formed-stringify

[44] 8.1 RFC 8259: https://tools.ietf.org/html/rfc8259#section-8.1

[45] https://github.com/tc39/proposal-regexp-legacy-features: https://github.com/tc39/proposal-regexp-legacy-features

[46] https://github.com/tc39/proposal-string-left-right-trim: https://github.com/tc39/proposal-string-left-right-trim

[47] https://github.com/tc39/proposal-string-matchall: https://github.com/tc39/proposal-string-matchall

[48] https://github.com/tc39/proposal-flatMap: https://github.com/tc39/proposal-flatMap

[49] личное сообщение: https://habr.com/ru/conversations/KasperGreen/

[50] https://github.com/KasperGreen/es10: https://github.com/KasperGreen/es10

[51] ECMAScript: https://ru.wikipedia.org/wiki/ECMAScript

[52] Новые #приватные поля классов в JavaScript: https://medium.com/devschacht/javascripts-new-private-class-fields-c60daffe361b

[53] Обзор возможностей стандартов ES7, ES8 и ES9: https://habr.com/ru/company/ruvds/blog/431872/

[54] Шебанг: https://ru.wikipedia.org/wiki/%D0%A8%D0%B5%D0%B1%D0%B0%D0%BD%D0%B3_(Unix)

[55] BigInt — длинная арифметика в JavaScript: https://habr.com/ru/post/354930/

[56] Источник: https://habr.com/ru/post/437806/?utm_campaign=437806