10 фич JavaScript, которые можно начать использовать прямо сейчас
27 июл 2022 · 03:06
Новые возможности ECMAScript 2022 включают в себя ожидание на верхнем уровне, индексы соответствия RegExp, новые поля классов public и private и многое другое. Давайте приступим!
imgpreview.jpg78.72 KB
ECMAScript 2022 (ES13) был выпущен 22 июня и содержит последнюю партию новых функций для Javascript. Каждая технологическая спецификация - это веха в непрерывном танце с реальным использованием. Спецификация ECMAScript реагирует на это, формализуя новые возможности. Они, в свою очередь, устанавливают новый базовый уровень для дальнейшего развития JavaScript.
Спецификация ES13 привносит восемь новых возможностей для JavaScript. Давайте начнем знакомство с этими новыми возможностями, которые вы можете использовать уже сегодня.
Ранее стандартным подходом при объявлении поля-члена внутри ключевого слова class было введение его в конструктор. Новейшая спецификация ECMAScript позволяет нам определять член встраиваемого поля как часть тела класса. Как показано в примере 1, мы можем использовать хэштег для обозначения приватного поля.
Пример 1. Совмещаем публичные и приватные поля класса:
classSong { title = «»; #artist = «»; constructor(title, artist){ this.title = title; this.#artist = artist; } } let song1 = newSong(«Only a Song», «Van Morrison» ); console.log(song1.title); // outputs “Only a Song” console.log(song1.artist); // outputs undefined
В первом примере мы определяем класс Song, используя ключевое слово class. Этот класс имеет два члена, название и исполнитель. Член artist имеет префикс в виде символа хэша, поэтому он является приватным. Мы разрешаем устанавливать эти поля в конструкторе. Обратите внимание, что конструктор должен обращаться к this.# artist с префиксом хэша еще раз, иначе он перезапишет поле публичным членом.
Далее мы определяем экземпляр класса Song, устанавливая оба поля через конструктор. Затем мы выводим поля в консоль. Дело в том, что song1.artist не виден внешнему миру и выводит неопределенное значение.
Заметим также, что даже song1.hasOwnProperty(«artist» ) вернет false. Кроме того, мы не сможем создать приватные поля класса позже с помощью присваивания.
В целом, это приятное дополнение, делающее код чище. Большинство браузеров уже давно поддерживают публичные и приватные поля экземпляра, и приятно видеть их официальное включение.
Методы и аксессоры частных экземпляров
Символ хэша также работает как префикс для методов и аксессоров. Влияние на видимость точно такое же, как и в случае с приватными полями экземпляра. Так, вы можете добавить приватный сеттер и публичный геттер к полю Song.artist, как показано в примере 2.
Пример 2. Методы и аксессоры частных экземпляров:
classSong { title = «»; #artist = «»; constructor(title, artist){ this.title = title; this.#artist = artist; } get getArtist() { returnthis.#artist; } set #setArtist(artist) { this.#artist = artist; } }
Статические члены
Предложение о полях класса также вводит статические члены. Они выглядят и работают аналогично тому, как это делается в Java: если член имеет ключевое слово-модификатор static, то он существует в классе, а не в экземплярах объектов. Вы можете добавить статический член в класс Song, как показано в примере 3.
Пример 3. Добавление статического члена в класс:
classSong { static label = «Exile»; }
Тогда поле будет доступно только через имя класса, Song.label. В отличие от Java, экземпляры JavaScript не хранят ссылку на общую статическую переменную. Обратите внимание, что можно иметь статическое приватное поле со статической #label; то есть приватное статическое поле.
Индексы совпадения регулярных выражений
Regex matchбыл обновлен, чтобы включать больше информации о группах соответствия. По соображениям производительности эта информация включается только в том случае, если к регулярному выражению добавлен флаг /d. (Более подробное описание значения /d regex см. в RegExp Match Indices for ECMAScript).
В принципе, использование флага /d заставляет механизм regex включать начало и конец всех совпадающих подстрок. Когда флаг присутствует, свойство indices в результатах exec будет содержать двумерный массив, где первое измерение представляет совпадение, а второе - начало и конец совпадения.
В случае именованных групп в индексах будет присутствовать член под названием groups, первое измерение которого содержит имя группы. Рассмотрим пример 4, который взят отсюда.
В примере 4 мы создаем регулярное выражение, которое соответствует символу a один или более раз, а затем именованную группу соответствия (с именем Z), которая соответствует символу z ноль или более раз.
В первом блоке кода демонстрируется, что m1.indices[0][0] и m1.indices[0][1] содержат 1 и 5 соответственно. Это потому, что первым совпадением для regex является строка от первого a до строки, заканчивающейся на z. Блок 2 показывает то же самое для символа z.
В блоке 3 показан доступ к первому измерению с именованной группой через m1.indices.groups. Есть одна совпадающая группа - последний символ z, и она имеет начало 4 и конец 5.
Наконец, блок 4 демонстрирует, что несопоставленные индексы и группы возвращают неопределенный результат.
В итоге, если вам нужен доступ к деталям сопоставления групп в строке, теперь вы можете использовать функцию regex match indices для их получения.
Высокоуровневое ожидание
Спецификация ECMAScript теперь включает возможность упаковывать асинхронные модули. Когда вы импортируете модуль, обернутый в await, включающий модуль не будет выполняться, пока не будут выполнены все await. Это позволяет избежать потенциальных ситуаций гонки при работе с взаимозависимыми вызовами асинхронных модулей. Подробности см. в предложении высокоуровневого await.
В примере 5 приведен пример, заимствованный отсюда.
Пример 5. Высокоуровневый await
// awaiting.mjs import { process } from «./some-module.mjs»; constdynamic = import(computedModuleSpecifier); const data = fetch(url); exportconst output = process((await dynamic).default, await data); // usage.mjs import { output } from «./awaiting.mjs»; exportfunction outputPlusValue(value) { return output + value }
Обратите внимание в файле awaiting.mjs на ключевое слово await перед использованием зависимых модулей dynamic и data. Это означает, что когда usage.mjs импортирует awaiting.mjs, usage.mjs не будет выполняться, пока зависимости awaiting.mjs не закончат загрузку.
Новые эргономичные проверки для приватных полей
Как разработчики, мы хотим код, который удобен - для этого были сделаны эргономичные приватные поля. Эта новая возможность позволяет нам проверять наличие приватного поля у класса, не прибегая к обработке исключений.
В примере 6 показан этот новый, эргономичный способ проверки наличия приватного поля изнутри класса с помощью ключевого слова in.
Пример 6. Проверка существования приватного поля:
classSong { #artist; checkField(){ return #artist in this; } } let foo = newSong(); foo.checkField(); // true
Пример 6 является надуманным, но идея понятна. Когда вам понадобится проверить класс на наличие закрытого поля, вы можете использовать формат:# fieldName in object.
Отрицательная индексация с помощью.at()
Прошли времена arr[arr.length -2]. Метод .at для встроенных индексируемых элементов теперь поддерживает отрицательные индексы, как показано в примере 7.
Пример 7. Отрицательный индекс с помощью.at():
let foo = [1,2,3,4,5]; foo.at(3); // == 3 hasOwn
hasOwn
Object.hasOwn - это улучшенная версия Object.hasOwnProperty. Она работает в некоторых исключительных случаях, например, когда объект создается с помощью Object.create(null). Обратите внимание, что hasOwn является статическим методом - он не существует для экземпляров.
Пример 8. hasOwn() в действии:
let foo = Object.create(null); foo.hasOwnProperty = function(){}; Object.hasOwnProperty(foo, 'hasOwnProperty'); // Error: Cannot convert object to primitive value Object.hasOwn(foo, 'hasOwnProperty'); // true
В примере 8 показано, что вы можете использовать Object.hasOwn для экземпляра foo, созданного с помощью Object.create(null).
Статический блок класса
Вот шанс для разработчиков Java сказать: «О, у нас это было с 90-х годов». ES 2022 вводит в JavaScript статические блоки инициализации. По сути, вы можете использовать ключевое слово static в блоке кода, который запускается при загрузке класса, и он будет иметь доступ к статическим членам.
В примере 9 приведен простой пример использования статического блока для инициализации статического значения.
И последнее, но не менее важное: класс Error теперь включает в себя поддержку причин. Это позволяет использовать в цепочках ошибок стековые трассировки, подобные Java. Конструктор ошибок теперь позволяет использовать объект options, который включает поле cause, как показано в примере 10.
Понравилась статья? Тогда ставьте лайки, пишите комментарии, делитесь ею с друзьями, а также подписывайтесь на нас тут и на других площадках (ссылка в шапке профиля).
{"document": [{"text": [{"type": "string", "attributes": {"italic": true}, "string": "Новые возможности ECMAScript 2022 включают в себя ожидание на верхнем уровне, индексы соответствия RegExp, новые поля классов public и private и многое другое. Давайте приступим!"}], "attributes": []}, {"text": [{"type": "attachment", "attributes": {"presentation": "gallery"}, "attachment": {"caption": "", "contentType": "image/jpeg", "filename": "imgpreview.jpg", "filesize": 80606, "height": 540, "pic_id": 108613, "url": "https://storage.yandexcloud.net/pabliko.files/article_cloud_image/2022/07/27/imgpreview_JMSsPTE.jpeg", "width": 960}}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "ECMAScript 2022 (ES13) был выпущен 22 июня и содержит последнюю партию новых функций для Javascript. Каждая технологическая спецификация - это веха в непрерывном танце с реальным использованием. Спецификация ECMAScript реагирует на это, формализуя новые возможности. Они, в свою очередь, устанавливают новый базовый уровень для дальнейшего развития JavaScript."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Спецификация ES13 привносит "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposals/blob/main/finished-proposals.md"}, "string": "восемь новых возможностей для JavaScript"}, {"type": "string", "attributes": {}, "string": ". Давайте начнем знакомство с этими новыми возможностями, которые вы можете использовать уже сегодня."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Поля классов"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-class-fields"}, "string": "Поля классов"}, {"type": "string", "attributes": {}, "string": " - это зонтичное предложение, которое включает в себя несколько улучшений для работы с членами классов JavaScript: "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-class-fields"}, "string": "публичные и приватные поля экземпляра класса"}, {"type": "string", "attributes": {}, "string": ", "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-private-methods"}, "string": "приватные методы и аксессоры экземпляра"}, {"type": "string", "attributes": {}, "string": ", а также "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-static-class-features"}, "string": "статические функции класса"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Публичные и приватные поля экземпляра"}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Ранее стандартным подходом при объявлении поля-члена внутри ключевого слова "}, {"type": "string", "attributes": {"bold": true}, "string": "class "}, {"type": "string", "attributes": {}, "string": "было введение его в конструктор. Новейшая спецификация ECMAScript позволяет нам определять член встраиваемого поля как часть тела класса. Как показано в примере 1, мы можем использовать хэштег для обозначения приватного поля."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 1. Совмещаем публичные и приватные поля класса:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "class"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": " {\ntitle = «»;\n#"}, {"type": "string", "attributes": {"italic": true}, "string": "artist = «»;"}, {"type": "string", "attributes": {}, "string": "\nconstructor(title, artist){\n"}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".title = title;\n"}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".#artist = artist;\n}\n}\n"}, {"type": "string", "attributes": {"bold": true}, "string": "let"}, {"type": "string", "attributes": {}, "string": " song1 = "}, {"type": "string", "attributes": {"bold": true}, "string": "new"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": "(«Only a Song», «Van Morrison» );\nconsole.log(song1.title);\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// outputs “Only a Song”"}, {"type": "string", "attributes": {}, "string": "\nconsole.log(song1.artist);\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// outputs undefined"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "В первом примере мы определяем класс "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": ", используя ключевое слово "}, {"type": "string", "attributes": {"bold": true}, "string": "class"}, {"type": "string", "attributes": {}, "string": ". Этот класс имеет два члена, название и исполнитель. Член "}, {"type": "string", "attributes": {"bold": true}, "string": "artist "}, {"type": "string", "attributes": {}, "string": "имеет префикс в виде символа хэша, поэтому он является приватным. Мы разрешаем устанавливать эти поля в конструкторе. Обратите внимание, что конструктор должен обращаться к "}, {"type": "string", "attributes": {"bold": true}, "string": "this.# artist"}, {"type": "string", "attributes": {}, "string": " с префиксом хэша еще раз, иначе он перезапишет поле публичным членом."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Далее мы определяем экземпляр класса "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": ", устанавливая оба поля через конструктор. Затем мы выводим поля в консоль. Дело в том, что "}, {"type": "string", "attributes": {"bold": true}, "string": "song1.artist"}, {"type": "string", "attributes": {}, "string": " не виден внешнему миру и выводит неопределенное значение."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Заметим также, что даже "}, {"type": "string", "attributes": {"bold": true}, "string": "song1.hasOwnProperty(«artist» )"}, {"type": "string", "attributes": {}, "string": " вернет "}, {"type": "string", "attributes": {"bold": true}, "string": "false"}, {"type": "string", "attributes": {}, "string": ". Кроме того, мы не сможем создать приватные поля класса позже с помощью присваивания."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "В целом, это приятное дополнение, делающее код чище. Большинство браузеров уже давно поддерживают публичные и приватные поля экземпляра, и приятно видеть их официальное включение."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Методы и аксессоры частных экземпляров"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": ""}, {"type": "string", "attributes": {}, "string": "Символ хэша также работает как префикс для методов и аксессоров. Влияние на видимость точно такое же, как и в случае с приватными полями экземпляра. Так, вы можете добавить приватный сеттер и публичный геттер к полю "}, {"type": "string", "attributes": {"bold": true}, "string": "Song.artist"}, {"type": "string", "attributes": {}, "string": ", как показано в примере 2."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 2. Методы и аксессоры частных экземпляров:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "class"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": " {\ntitle = «»;\n#"}, {"type": "string", "attributes": {"italic": true}, "string": "artist = «»;"}, {"type": "string", "attributes": {}, "string": "\nconstructor(title, artist){\n"}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".title = title;\n"}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".#artist = artist;\n}\n"}, {"type": "string", "attributes": {"bold": true}, "string": "get"}, {"type": "string", "attributes": {}, "string": " getArtist() {\n"}, {"type": "string", "attributes": {"bold": true}, "string": "return"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".#artist;\n}\n"}, {"type": "string", "attributes": {"bold": true}, "string": "set "}, {"type": "string", "attributes": {}, "string": "#"}, {"type": "string", "attributes": {"italic": true}, "string": "setArtist(artist) {"}, {"type": "string", "attributes": {}, "string": "\n"}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".#artist = artist;\n}\n}"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Статические члены"}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Предложение о полях класса также вводит статические члены. Они выглядят и работают аналогично тому, как это делается в "}, {"type": "string", "attributes": {"bold": true}, "string": "Java"}, {"type": "string", "attributes": {}, "string": ": если член имеет ключевое слово-модификатор "}, {"type": "string", "attributes": {"bold": true}, "string": "static"}, {"type": "string", "attributes": {}, "string": ", то он существует в классе, а не в экземплярах объектов. Вы можете добавить статический член в класс "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": ", как показано в примере 3."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 3. Добавление статического члена в класс:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "class"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": " {\n"}, {"type": "string", "attributes": {"bold": true}, "string": "static"}, {"type": "string", "attributes": {}, "string": " label = «Exile»;\n}"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "Тогда поле будет доступно только через имя класса, "}, {"type": "string", "attributes": {"bold": true}, "string": "Song.label"}, {"type": "string", "attributes": {}, "string": ". В отличие от Java, экземпляры JavaScript не хранят ссылку на общую статическую переменную. Обратите внимание, что можно иметь статическое приватное поле со статической #"}, {"type": "string", "attributes": {"bold": true}, "string": "label"}, {"type": "string", "attributes": {}, "string": "; то есть приватное статическое поле."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Индексы совпадения регулярных выражений"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {}, "string": "Regex "}, {"type": "string", "attributes": {"bold": true}, "string": "match"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-regexp-match-indices"}, "string": "был обновлен"}, {"type": "string", "attributes": {}, "string": ", чтобы включать больше информации о группах соответствия. По соображениям производительности эта информация включается только в том случае, если к регулярному выражению добавлен флаг "}, {"type": "string", "attributes": {"bold": true}, "string": "/d"}, {"type": "string", "attributes": {}, "string": ". (Более подробное описание значения "}, {"type": "string", "attributes": {"bold": true}, "string": "/d"}, {"type": "string", "attributes": {}, "string": " regex см. в "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-regexp-match-indices"}, "string": "RegExp Match Indices for ECMAScript"}, {"type": "string", "attributes": {}, "string": ")."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "В принципе, использование флага "}, {"type": "string", "attributes": {"bold": true}, "string": "/d"}, {"type": "string", "attributes": {}, "string": " заставляет механизм regex включать начало и конец всех совпадающих подстрок. Когда флаг присутствует, свойство "}, {"type": "string", "attributes": {"bold": true}, "string": "indices "}, {"type": "string", "attributes": {}, "string": "в результатах "}, {"type": "string", "attributes": {"bold": true}, "string": "exec "}, {"type": "string", "attributes": {}, "string": "будет содержать двумерный массив, где первое измерение представляет совпадение, а второе - начало и конец совпадения."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "В случае именованных групп в индексах будет присутствовать член под названием "}, {"type": "string", "attributes": {"bold": true}, "string": "groups"}, {"type": "string", "attributes": {}, "string": ", первое измерение которого содержит имя группы. Рассмотрим пример 4, который взят "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-regexp-match-indices#examples"}, "string": "отсюда"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 4. Индексы групп Regex:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " re1 = /a+(?<Z>z)?/d;\n\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// block 1"}, {"type": "string", "attributes": {}, "string": "\n"}, {"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " s1 = «xaaaz»;\n"}, {"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " m1 = re1."}, {"type": "string", "attributes": {"bold": true}, "string": "exec"}, {"type": "string", "attributes": {}, "string": "(s1);\nm1.indices[0][0] === 1;\nm1.indices[0][1] === 5;\ns1.slice(...m1.indices[0]) === «aaaz»;\n\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// block 2"}, {"type": "string", "attributes": {}, "string": "\nm1.indices[1][0] === 4;\nm1.indices[1][1] === 5;\ns1.slice(...m1.indices[1]) === «z»;\n\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// block 3"}, {"type": "string", "attributes": {}, "string": "\nm1.indices.groups[«Z» ][0] === 4;\nm1.indices.groups[«Z» ][1] === 5;\ns1.slice(...m1.indices.groups[«Z» ]) === «z»;\n\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// block 4"}, {"type": "string", "attributes": {}, "string": "\n"}, {"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " m2 = re1."}, {"type": "string", "attributes": {"bold": true}, "string": "exec"}, {"type": "string", "attributes": {}, "string": "(«xaaay» );\nm2.indices[1] === "}, {"type": "string", "attributes": {"bold": true}, "string": "undefined"}, {"type": "string", "attributes": {}, "string": ";\nm2.indices.groups[«Z» ] === "}, {"type": "string", "attributes": {"bold": true}, "string": "undefined"}, {"type": "string", "attributes": {}, "string": ";"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "В примере 4 мы создаем регулярное выражение, которое соответствует символу "}, {"type": "string", "attributes": {"bold": true}, "string": "a"}, {"type": "string", "attributes": {}, "string": " один или более раз, а затем именованную группу соответствия (с именем "}, {"type": "string", "attributes": {"bold": true}, "string": "Z"}, {"type": "string", "attributes": {}, "string": "), которая соответствует символу "}, {"type": "string", "attributes": {"bold": true}, "string": "z "}, {"type": "string", "attributes": {}, "string": "ноль или более раз."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "В первом блоке"}, {"type": "string", "attributes": {}, "string": " кода демонстрируется, что "}, {"type": "string", "attributes": {"bold": true}, "string": "m1.indices[0][0]"}, {"type": "string", "attributes": {}, "string": " и "}, {"type": "string", "attributes": {"bold": true}, "string": "m1.indices[0][1]"}, {"type": "string", "attributes": {}, "string": " содержат 1 и 5 соответственно. Это потому, что первым совпадением для regex является строка от первого "}, {"type": "string", "attributes": {"bold": true}, "string": "a"}, {"type": "string", "attributes": {}, "string": " до строки, заканчивающейся на "}, {"type": "string", "attributes": {"bold": true}, "string": "z"}, {"type": "string", "attributes": {}, "string": ". "}, {"type": "string", "attributes": {"italic": true}, "string": "Блок 2"}, {"type": "string", "attributes": {}, "string": " показывает то же самое для символа "}, {"type": "string", "attributes": {"bold": true}, "string": "z"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "В блоке 3"}, {"type": "string", "attributes": {}, "string": " показан доступ к первому измерению с именованной группой через "}, {"type": "string", "attributes": {"bold": true}, "string": "m1.indices.groups"}, {"type": "string", "attributes": {}, "string": ". Есть одна совпадающая группа - последний символ "}, {"type": "string", "attributes": {"bold": true}, "string": "z"}, {"type": "string", "attributes": {}, "string": ", и она имеет начало 4 и конец 5."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Наконец, "}, {"type": "string", "attributes": {"italic": true}, "string": "блок 4"}, {"type": "string", "attributes": {}, "string": " демонстрирует, что несопоставленные индексы и группы возвращают неопределенный результат."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "В итоге, если вам нужен доступ к деталям сопоставления групп в строке, теперь вы можете использовать функцию "}, {"type": "string", "attributes": {"bold": true}, "string": "regex match indices"}, {"type": "string", "attributes": {}, "string": " для их получения."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Высокоуровневое ожидание"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {}, "string": "Спецификация ECMAScript теперь включает возможность упаковывать асинхронные модули. Когда вы импортируете модуль, обернутый в "}, {"type": "string", "attributes": {"bold": true}, "string": "await"}, {"type": "string", "attributes": {}, "string": ", включающий модуль не будет выполняться, пока не будут выполнены все "}, {"type": "string", "attributes": {"bold": true}, "string": "await"}, {"type": "string", "attributes": {}, "string": ". Это позволяет избежать потенциальных ситуаций гонки при работе с взаимозависимыми вызовами асинхронных модулей. Подробности см. в "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-top-level-await"}, "string": "предложении высокоуровневого "}, {"type": "string", "attributes": {"bold": true, "href": "https://github.com/tc39/proposal-top-level-await"}, "string": "await"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "В примере 5"}, {"type": "string", "attributes": {}, "string": " приведен пример, заимствованный "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-top-level-await#solution-top-level-await"}, "string": "отсюда"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 5. Высокоуровневый await"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "// awaiting.mjs"}, {"type": "string", "attributes": {}, "string": "\n"}, {"type": "string", "attributes": {"bold": true}, "string": "import"}, {"type": "string", "attributes": {}, "string": " { process } "}, {"type": "string", "attributes": {"bold": true}, "string": "from"}, {"type": "string", "attributes": {}, "string": " «./some-module.mjs»;\n"}, {"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "dynamic"}, {"type": "string", "attributes": {}, "string": " = "}, {"type": "string", "attributes": {"bold": true}, "string": "import"}, {"type": "string", "attributes": {}, "string": "(computedModuleSpecifier);\n"}, {"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " data = fetch(url);\n"}, {"type": "string", "attributes": {"bold": true}, "string": "export"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "const"}, {"type": "string", "attributes": {}, "string": " output = process((await "}, {"type": "string", "attributes": {"bold": true}, "string": "dynamic"}, {"type": "string", "attributes": {}, "string": ")."}, {"type": "string", "attributes": {"bold": true}, "string": "default"}, {"type": "string", "attributes": {}, "string": ", await data);\n"}, {"type": "string", "attributes": {"italic": true}, "string": "// usage.mjs"}, {"type": "string", "attributes": {}, "string": "\n"}, {"type": "string", "attributes": {"bold": true}, "string": "import"}, {"type": "string", "attributes": {}, "string": " { output } "}, {"type": "string", "attributes": {"bold": true}, "string": "from"}, {"type": "string", "attributes": {}, "string": " «./awaiting.mjs»;\n"}, {"type": "string", "attributes": {"bold": true}, "string": "export"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "function"}, {"type": "string", "attributes": {}, "string": " outputPlusValue(value) { "}, {"type": "string", "attributes": {"bold": true}, "string": "return"}, {"type": "string", "attributes": {}, "string": " output + value }\n\nconsole.log(outputPlusValue(100));\nsetTimeout(() => console.log(outputPlusValue(100), 1000);"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "Обратите внимание в файле "}, {"type": "string", "attributes": {"bold": true}, "string": "awaiting.mjs"}, {"type": "string", "attributes": {}, "string": " на ключевое слово "}, {"type": "string", "attributes": {"bold": true}, "string": "await"}, {"type": "string", "attributes": {}, "string": " перед использованием зависимых модулей "}, {"type": "string", "attributes": {"bold": true}, "string": "dynamic"}, {"type": "string", "attributes": {}, "string": " и "}, {"type": "string", "attributes": {"bold": true}, "string": "data"}, {"type": "string", "attributes": {}, "string": ". Это означает, что когда "}, {"type": "string", "attributes": {"bold": true}, "string": "usage.mjs"}, {"type": "string", "attributes": {}, "string": " импортирует "}, {"type": "string", "attributes": {"bold": true}, "string": "awaiting.mjs"}, {"type": "string", "attributes": {}, "string": ", "}, {"type": "string", "attributes": {"bold": true}, "string": "usage.mjs"}, {"type": "string", "attributes": {}, "string": " не будет выполняться, пока зависимости "}, {"type": "string", "attributes": {"bold": true}, "string": "awaiting.mjs"}, {"type": "string", "attributes": {}, "string": " не закончат загрузку."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Новые эргономичные проверки для приватных полей"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {}, "string": "Как разработчики, мы хотим код, который удобен - для этого были сделаны "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-private-fields-in-in"}, "string": "эргономичные приватные поля"}, {"type": "string", "attributes": {}, "string": ". Эта новая возможность позволяет нам проверять наличие приватного поля у класса, не прибегая к обработке исключений."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "В примере 6"}, {"type": "string", "attributes": {}, "string": " показан этот новый, эргономичный способ проверки наличия приватного поля изнутри класса с помощью ключевого слова "}, {"type": "string", "attributes": {"bold": true}, "string": "in"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 6. Проверка существования приватного поля:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "class"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": " {\n#"}, {"type": "string", "attributes": {"italic": true}, "string": "artist;"}, {"type": "string", "attributes": {}, "string": "\ncheckField(){\n"}, {"type": "string", "attributes": {"bold": true}, "string": "return"}, {"type": "string", "attributes": {}, "string": " #"}, {"type": "string", "attributes": {"italic": true}, "string": "artist in this;"}, {"type": "string", "attributes": {}, "string": "\n}\n}\n"}, {"type": "string", "attributes": {"bold": true}, "string": "let"}, {"type": "string", "attributes": {}, "string": " foo = "}, {"type": "string", "attributes": {"bold": true}, "string": "new"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Song"}, {"type": "string", "attributes": {}, "string": "();\nfoo.checkField(); "}, {"type": "string", "attributes": {"italic": true}, "string": "// true"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "Пример 6"}, {"type": "string", "attributes": {}, "string": " является надуманным, но идея понятна. Когда вам понадобится проверить класс на наличие закрытого поля, вы можете использовать формат:"}, {"type": "string", "attributes": {"bold": true}, "string": "# fieldName in object"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Отрицательная индексация с помощью.at()"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {}, "string": "Прошли времена "}, {"type": "string", "attributes": {"bold": true}, "string": "arr[arr.length -2]"}, {"type": "string", "attributes": {}, "string": ". "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-relative-indexing-method"}, "string": "Метод "}, {"type": "string", "attributes": {"bold": true, "href": "https://github.com/tc39/proposal-relative-indexing-method"}, "string": ".at"}, {"type": "string", "attributes": {}, "string": " для встроенных индексируемых элементов теперь поддерживает отрицательные индексы, как показано "}, {"type": "string", "attributes": {"italic": true}, "string": "в примере 7"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 7. Отрицательный индекс с помощью.at():"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "let"}, {"type": "string", "attributes": {}, "string": " foo = [1,2,3,4,5];\nfoo.at(3); "}, {"type": "string", "attributes": {"italic": true}, "string": "// == 3"}, {"type": "string", "attributes": {}, "string": "\nhasOwn"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "hasOwn"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-accessible-object-hasownproperty"}, "string": "Object.hasOwn"}, {"type": "string", "attributes": {}, "string": " - это улучшенная версия "}, {"type": "string", "attributes": {"bold": true}, "string": "Object.hasOwnProperty"}, {"type": "string", "attributes": {}, "string": ". Она работает в некоторых исключительных случаях, например, когда объект создается с помощью "}, {"type": "string", "attributes": {"bold": true}, "string": "Object.create(null)"}, {"type": "string", "attributes": {}, "string": ". Обратите внимание, что "}, {"type": "string", "attributes": {"bold": true}, "string": "hasOwn"}, {"type": "string", "attributes": {}, "string": " является статическим методом - он не существует для экземпляров."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 8. hasOwn() в действии:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "let"}, {"type": "string", "attributes": {}, "string": " foo = "}, {"type": "string", "attributes": {"bold": true}, "string": "Object"}, {"type": "string", "attributes": {}, "string": ".create("}, {"type": "string", "attributes": {"bold": true}, "string": "null"}, {"type": "string", "attributes": {}, "string": ");\nfoo.hasOwnProperty = "}, {"type": "string", "attributes": {"bold": true}, "string": "function"}, {"type": "string", "attributes": {}, "string": "(){};\n"}, {"type": "string", "attributes": {"bold": true}, "string": "Object"}, {"type": "string", "attributes": {}, "string": ".hasOwnProperty(foo, 'hasOwnProperty'); "}, {"type": "string", "attributes": {"italic": true}, "string": "// Error: Cannot convert object to primitive value"}, {"type": "string", "attributes": {}, "string": "\n"}, {"type": "string", "attributes": {"bold": true}, "string": "Object"}, {"type": "string", "attributes": {}, "string": ".hasOwn(foo, 'hasOwnProperty'); "}, {"type": "string", "attributes": {"italic": true}, "string": "// true"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "В примере 8"}, {"type": "string", "attributes": {}, "string": " показано, что вы можете использовать "}, {"type": "string", "attributes": {"bold": true}, "string": "Object.hasOwn"}, {"type": "string", "attributes": {}, "string": " для экземпляра "}, {"type": "string", "attributes": {"bold": true}, "string": "foo"}, {"type": "string", "attributes": {}, "string": ", созданного с помощью "}, {"type": "string", "attributes": {"bold": true}, "string": "Object.create(null)"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {}, "string": "Статический блок класса"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {}, "string": "Вот шанс для разработчиков Java сказать: «О, у нас это было с 90-х годов». ES 2022 вводит в JavaScript "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-class-static-block"}, "string": "статические блоки инициализации"}, {"type": "string", "attributes": {}, "string": ". По сути, вы можете использовать ключевое слово "}, {"type": "string", "attributes": {"bold": true}, "string": "static "}, {"type": "string", "attributes": {}, "string": "в блоке кода, который запускается при загрузке класса, и он будет иметь доступ к статическим членам."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"italic": true}, "string": "В примере 9"}, {"type": "string", "attributes": {}, "string": " приведен простой пример использования статического блока для инициализации статического значения."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 9. Статический блок:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "class"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Foo"}, {"type": "string", "attributes": {}, "string": " {\n"}, {"type": "string", "attributes": {"bold": true}, "string": "static"}, {"type": "string", "attributes": {}, "string": " bar;\n"}, {"type": "string", "attributes": {"bold": true}, "string": "static"}, {"type": "string", "attributes": {}, "string": " {\n"}, {"type": "string", "attributes": {"bold": true}, "string": "this"}, {"type": "string", "attributes": {}, "string": ".bar = “test”;\n}\n}"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "Причина ошибки"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {}, "string": "И последнее, но не менее важное: класс "}, {"type": "string", "attributes": {"bold": true}, "string": "Error "}, {"type": "string", "attributes": {}, "string": "теперь включает в себя "}, {"type": "string", "attributes": {"href": "https://github.com/tc39/proposal-error-cause"}, "string": "поддержку причин"}, {"type": "string", "attributes": {}, "string": ". Это позволяет использовать в цепочках ошибок стековые трассировки, подобные Java. Конструктор ошибок теперь позволяет использовать объект "}, {"type": "string", "attributes": {"bold": true}, "string": "options"}, {"type": "string", "attributes": {}, "string": ", который включает поле "}, {"type": "string", "attributes": {"bold": true}, "string": "cause"}, {"type": "string", "attributes": {}, "string": ", как показано "}, {"type": "string", "attributes": {"italic": true}, "string": "в примере 10"}, {"type": "string", "attributes": {}, "string": "."}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Пример 10. Причина ошибки:"}], "attributes": []}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "throw"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "new"}, {"type": "string", "attributes": {}, "string": " "}, {"type": "string", "attributes": {"bold": true}, "string": "Error"}, {"type": "string", "attributes": {}, "string": "('Error message', { cause: errorCause });"}], "attributes": ["quote"]}, {"text": [{"type": "string", "attributes": {}, "string": "Заключение"}], "attributes": ["heading1"]}, {"text": [{"type": "string", "attributes": {"bold": true}, "string": "Понравилась статья? Тогда ставьте лайки, пишите комментарии, делитесь ею с друзьями, а также подписывайтесь на нас тут и на других площадках (ссылка в шапке профиля)."}], "attributes": []}], "selectedRange": [180, 180]}
Комментарии 0