Что нам даёт понимание спецификации языка ECMA Script? Разбираем стандарт ECMA262

от автора

Привет, Хабр! Меня зовут Александр, я разработчик NodeJS в SimbirSoft. Я 7 лет занимаюсь разработкой, и могу утверждать, что в процессе получения опыта работа специалиста становится все более творческой. Мы не просто стремимся заставить ПО работать нужным заказчику образом, а стараемся сделать все его части элегантными, производительными и легко поддерживаемыми. 

Язык программирования, являясь нашим главным инструментом, не статичен и постоянно развивается. Какие-то его части устаревают и отмирают, появляются новые фичи языка, отвечающие духу последних методологий по разработке ПО.

Я расскажу о сообществе, которое занято развитием нашего языка JavaScript. В первую очередь это организация ECMA International, которая разрабатывает стандарт языка ECMA Script, диалектом которого является JavaScript.

Мы разберем основные движки, реализующие стандарт ECMA Script, его ключевые разделы, опишем содержание на примере фичи. Рассмотрим, для чего изучать стандарт и как его дополнить, внеся свой вклад в сообщество разработчиков.

Что такое ECMA Script 

ECMA Script — это язык программирования, который был разработан компанией Ecma International и стандартизирован в спецификации ECMA-262. Он используется в качестве основы для создания других скриптовых языков, таких как JavaScript, JScript и ActionScript.

Реализацию стандарта ECMA-262 определяют производители JavaScript-движков — сред, где идёт непосредственное выполнение кода. Существует множество различных движков для JavaScript, но погоду как обычно задают крупные игроки: 

  • Google с его движком V8, который используется не только в браузерах на основе Chromium, но и в популярной серверной платформе NodeJS.

  • Mozilla с её движком SpiderMonkey.

  • Apple с её движком JavaScriptCore.

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

А если интересует реализация конкретной фичи из стандарта ECMAScript, можно забить её в поиск на сервисе MDN и посмотреть в раздел «Совместимость с браузерами». Также можно воспользоваться поиском на сервисе Can I use, который отображает поддержку фичи различными движками.

Стандарт имеет редакции — версии его развития. До 2015 года он развивался не ежегодными обновлениями и имел последовательные номера редакций: 1, 2, 3, 4, 5, 6. С 2015 года обновления стали ежегодными и номер редакции стал совпадать с годом её принятия. Например, ES6 и ES2015 — это одна и та же редакция стандарта.

Преимущества изучения стандарта ECMA262

  1. В первую очередь — это понимание основ языка. Стандарт ECMA Script описывает основные принципы и синтаксис JavaScript. Изучение стандарта помогает разработчикам глубже понять, как работает язык на фундаментальном уровне. Это знание позволяет лучше разбираться в коде, писать более эффективные и понятные программы, а также избегать распространенных ошибок.

  2. Позволяет быть на передовой развития технологий. Стандарт ECMA Script регулярно обновляется, и каждое новое издание приносит с собой улучшения и новые возможности. Например, ES6 (ECMAScript 2015) ввел такие важные функции, как стрелочные функции, классы, модули и многое другое. Знание последних версий стандарта позволяет разработчикам использовать современные возможности языка, повышая производительность и улучшая читаемость кода.

  3. Позволяет писать совместимый и кроссбраузерный код. Разные браузеры и среды выполнения могут поддерживать различные версии стандарта ECMA Script. Понимание стандарта помогает разработчикам писать код, который будет работать в различных средах, обеспечивая кроссбраузерную совместимость. Это особенно важно для веб-разработчиков, которые должны учитывать особенности работы разных браузеров.

  4. Позволяет писать оптимальный и производительный код. Изучение стандарта ECMA Script позволяет разработчикам лучше понимать, как оптимизировать код для повышения производительности. Например, знание особенностей работы с памятью, асинхронного программирования и других аспектов языка помогает создавать более быстрые и эффективные приложения.

  5. Помогает получить углубленное понимание работы популярных инструментов и библиотек. Многие популярные библиотеки и фреймворки, такие как React, Angular и Vue.js, активно используют возможности, предоставляемые стандартом ECMA Script. Понимание стандарта помогает разработчикам лучше разбираться в этих инструментах, эффективно их использовать и решать возникающие проблемы.

  6. Дает возможность быть готовым к будущему. JavaScript продолжает развиваться, и новые версии стандарта ECMA Script будут продолжать вводить новые возможности и улучшения. Изучение стандарта помогает разработчикам быть в курсе последних тенденций и готовиться к будущим изменениям в языке.

Ключевые разделы стандарта

На момент написания этой статьи последняя редакция ECMA2025 имеет 29 разделов и 9 приложений. Она написана в удобном виде html-документа. Разделы можно добавлять себе в закладки (Pins) с помощью всплывающего пункта меню «Pin». Также можно делиться ссылками на разделы или сохранять их в закладки браузера с помощью всплывающего пункта меню «Permalink».

Раздел «Introduction» (введение) расскажет нам о истории развития стандарта, его основателях и о том какие ключевые нововведения были в разных редакциях.

Далее я бы рекомендовал обратить внимание на разделы «Overview» и «Notational Conventions». В первом дается общий обзор языка ECMAScript, а во втором рассказывается принцип описания фичи в спецификации. Без раздела «Notational Conventions» будет сложнее понять о чём пишется в дальнейших разделах спецификации.

Ну а дальнейшие разделы как раз и посвящены описанию различных фичей языка ECMAScript.

String.prototype.isWellFormed

Давайте теперь ради интереса разберём одну из последних (на момент написания этой статьи) фич ECMAScript 2024: String.prototype.isWellFormed.

Узнать об этом нововведении можно из раздела «Introduction».

Копируем название «String.prototype.isWellFormed», вбиваем в левое верхнее поле «Search» и нам высвечивается ссылка «clause 22.1.3.10 String.prototype.isWellFormed ( )». Идём туда.

Мы видим довольно коротенький раздел. Давайте разбираться, о чём нам тут пишут.

Когда этот метод выполняется, он последовательно выполняет три шага.

В первом шаге мы определяем переменную «О» и присваиваем ей результат выполнения абстрактной операции «RequireObjectCoercible». В качестве аргумента используется значение текущего объекта (this value). В данном случае, если это была какая-то строка «foo», то передаётся эта строка.

Абстрактные операции — это внутренние функции, определенные в спецификации (с целью её сокращения). JavaScript движки не обязаны их создавать и могут иметь свою внутреннюю реализацию исходной фичи. Но обязаны следовать общей логике спецификации.

Что там за знак вопроса? Это сокращение для ещё одной абстрактной операции ReturnIfAbrupt. То есть знак вопроса заменяет более громоздкое написание: ReturnIfAbrupt(RequireObjectCoercible(this value)). Условно говоря, знак вопроса — это контроль исключения. Если абстрактная операция RequireObjectCoercible выкинет исключение, то мы его сразу же возвращаем как результат выполнения String.prototype.isWellFormed и на последующие шаги не переходим. Переменную «О» не создаём и ничего ей не присваиваем.

Абстрактная операция RequireObjectCoercible проверяет тип переданного ей аргумента. Если тип Undefined или Null — выкидывает исключение TypeError.

Итак, в результате выполнения первого шага мы получаем переменную «О» в которой должна быть исходная строка «foo» или выкинуто исключение TypeError.

Теперь давайте посмотрим, что происходит на шаге 2.

Тут мы определяем переменную «S» и присваиваем ей результат выполнения абстрактной операции ToString. В качестве аргумента мы передаём значение переменной «O» из первого шага.

Если ToString вернёт исключение, то мы сразу же возвращаем его.

Сама абстрактная операция ToString преобразует значение из переменной «O» в тип строки (String) или вернёт исключение.

Как мы видим, первые два шага — это проверка типа данных. Мы убеждаемся, что работаем со строкой.

В третьем шаге мы возвращаем результат выполнения абстрактной операции IsStringWellFormedUnicode, где и скрыта основная логика String.prototype.isWellFormed. Давайте посмотрим, что там происходит.

Тут даётся пояснение, что данная абстрактная операция проверяет последовательность символов в строке, чтобы она соответствовала стандарту UTF-16. Символы в кодировке могут кодироваться как двумя байтами, так и четырьмя (два по два байта). Последний вариант называется в UTF-16 суррогатной парой. Если так получилось, что по какой-то неизвестной причине в последовательности отсутствует пара, которая должна быть, то такой символ будет не полным (битым). И данная абстрактная операция вернет false — что будет обозначать, что переданная ей строка (последовательность символов юникода) не корректная (повреждённая). «Well formed» тут обозначает не битая строка с символами юникода.

Итак, в абстрактной операции  IsStringWellFormedUnicode мы видим 4 шага.

  1. На первом шаге мы переменной len присваиваем длину исходной строки. 

Следует понимать, что в спецификации ECMA-262, длина строки измеряется в количестве 16-битных кодовых единиц (code units). Например, латинская буква «f» будет занимать одну кодовую единицу. А какое-нибудь эмодзи может занимать 2 кодовых единицы.

  1. На шаге 2 мы переменной k присваиваем 0.

  2. На шаге 3 начинается цикл while с условием k < len и тремя вложенными в него шагами (a, b, c).

  3. На шаге 3a переменной cp присваиваем результат работы абстрактной операции CodePointAt. Я не буду тут уже расписывать алгоритм её работы. Кому интересно, могут ознакомится с ней самостоятельно. Её суть в том, что она возвращает объект, у которого есть 3 поля: [[CodePoint]] (код символа), [[CodeUnitCount]] (количество кодовых едениц: 1 или 2) и [[IsUnpairedSurrogate]] (суррогат без найденной пары — true или false).

Что за двойные квадратные скобки? Это так называемые внутренние слоты или методы. Это так в спецификации обозначают свойства объекта. Представим себе классический JS-объект: o ={ foo: `bar` }, то языком спецификации он будет выглядеть так: o.[[foo]].

Пример возвращаемого объекта абстрактной операции CodePointAt можно представить так: { CodePoint: 0xD83D, CodeUnitCount: 1, IsUnpairedSurrogate: false }.

На шаге 3b если свойство IsUnpairedSurrogate объекта cp равно true (найден суррогат без пары), абстрактная операция IsStringWellFormedUnicode вернёт false — значит строка битая.

На шаге 3c переменную k увеличиваем на 1 или 2, чтобы перейти к следующему символу в строке.

Если за цикл не было найдено суррогатов без пары, то абстрактная операция  IsStringWellFormedUnicode вернёт true — строка не повреждена и все символы юникода корректные.

И вот мы теперь имеем представление, как работает метод String.prototype.isWellFormed согласно спецификации.

На MDN можно найти статью, которая описывает работу этого метода непосредственно уже в JavaScript-языке. В разделе «Browser compatibility» мы видим, что эту фичу уже реализовали все платформы и браузеры.

Теперь мы получили более менее общее представление, как описаны элементы нашего языка в спецификации ECMA 262 (ECMAScript) и как они примерно работают изнутри.

Как дополнить стандарт самому?

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

Дело в том, что любой разработчик может прийти в группу TC39, которая разрабатывает и поддерживает стандарт ECMAScript и подать предложение по улучшению и развитию языка. Предложение оформляется в виде проекта на GitHub в группе tc39.

Каждое предложение проходит 5 стадий.

0 — Предложение верно оформлено. Но не факт, что комиссия обратит на него внимание.

1 — Комитет обратил внимание на это предложение и ищет для него слот времени для обсуждения.

2 — Разрабатывается черновик решения для включения в стандарт. Но не факт, что эта фича может перейти на следующую стадию.

2.7 — Предложение одобрено и проходит всестороннюю оценку, тестирование и изучается возможность реализации фичи в движках JavaScript.

3 — Предложение рекомендовано к реализации. Возможны мелкие правки.

4 — Предлагаемая фича завершена и готова к включению в стандарт. Больше правок не будет.

Вот и веб-разработчик Даниел из Германии задумался о том, что стандарту не хватает функции, разобранной нами выше.

В своем предложении он написал: 

«Модель компонентов WebAssembly требует правильно сформированных строк, как и некоторые языки программирования, компилируемые в JS, многие кодировки данных, сетевые интерфейсы, интерфейсы файловой системы и т. д. Сопряжение строк JavaScript с такими API является распространенным вариантом использования, который поэтому страдает от проблем с преобразованием. В частности, поскольку преобразование из DOMString в USVString осуществляется с потерями (обычными вариантами являются замена непарных суррогатов или выдача ошибки), существует регулярная необходимость проверки строк как внутри платформы, так и для определенных сценариев использования в пользовательской среде».

С работой по продвижению предложения и коммуникацию с представителями tc39 можно ознакомится в Pull Requests.

Из этого примера видно, как сообщество разработчиков может влиять на свой язык и улучшать его. Но это не единственный рычаг влияния.

Примерно раз в год проводится открытый опрос по языку JavaScript и каждый желающий может принять в нём участие. Он называется «State of JavaScript». Начиная с 2016 года, в опросе ежегодно участвуют более 20 000 разработчиков для того, чтобы изучить текущие и будущие тенденции.

Принять в нём участие и ознакомится с результатами прошлых опросов можно на официальном сайте этого опроса. Там же можно подключить свою электронную почту для получения уведомления о начале следующего опроса. Обычно они проходят в декабре.

Вместо заключения

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

Полезные материалы:

  1. ECMAScript Language Specification

  2. Чем отличаются JavaScript и ECMAScript?

  3. Wikipedia: ECMAScript

  4. Wikipedia: JavaScript

  5. Понимание спецификации ECMAScript, часть 1

  6. Понимание спецификации ECMAScript, часть 2

  7. MDN: JavaScript implementations

  8. SpiderMonkey

  9. V8

  10. JavaScriptCore

  11. Wikipedia: Chakra

  12. ECMAScript Compatibility Table

Спасибо за внимание!

Больше авторских материалов для frontend-разработчиков от моих коллег читайте в соцсетях SimbirSoft – ВКонтакте и Telegram.


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


Комментарии

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

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