Реализованы ли внутренние слоты и внутренние методы движками JavaScript? - PullRequest
0 голосов
/ 07 февраля 2020

Я читал ECMA2019 (то же самое верно и в ES6), где я нашел:

Каждый объект в движке ECMAScript связан с набором внутренних методов это определяет его поведение во время выполнения. Эти внутренние методы не являются частью языка ECMAScript. Они определены этой спецификацией исключительно для пояснительных целей. Однако каждый объект в реализации ECMAScript должен вести себя так, как указано внутренними методами, связанными с ним. Точный способ, которым это достигается, определяется реализацией.

Я также обнаружил, что переполнение стека question1 и question2 и что их ответы не кажется, не дает мне ответ, который я ищу.

Мой вопрос прост. Если JavaScript движки решат не реализовывать некоторые из них, то как они будут обеспечивать это утверждение выше spe c -

Однако каждый объект в реализации ECMAScript должен вести себя так, как указано внутренние методы, связанные с ним.

Давайте рассмотрим пример:

[[GetPrototypeOf]], [[Get]], [[Set]], [[GetOwnProperty]] et c необходимы внутренние методы. Если двигатель JavaScript отказывается их реализовывать, как он достигает этой функциональности? Ясно, что они должны реализовать это, просто чтобы они могли выбрать другое имя метода и другую сигнатуру метода, поскольку это не предписано spe c для них?

Где я не прав?

Тоже для внутренних слотов тоже? Если у них нет внутренних переменных, хранящих это состояние, как они будут поддерживать состояние этого объекта при запросе?

РЕДАКТИРОВАТЬ : Я добавлю больше деталей, чтобы прояснить мой вопрос. Давайте возьмем пример Object.getPrototypeOf(). Это API для внутреннего поведения [[GetPrototypeOf]], и возможен алгоритм для его реализации. Вопрос не в том, как реализовать это поведение - о том, есть ли поведение или нет! и все еще удовлетворяющий spe c общему поведению объекта.

1 Ответ

2 голосов
/ 08 февраля 2020

V8 разработчик здесь. Я думаю, что на этот вопрос в основном уже отвечали уже в комментариях, поэтому я просто подведу итоги.

Реализуются ли внутренние слоты и внутренние методы механизмами JavaScript?

Обычно нет; двигатель просто ведет себя , как если бы его внутренности были структурированы таким образом. Некоторые части реализации могут быть очень близки к структуре spe c, если это удобно.

Один из способов выразить это было бы так: вы могли бы реализовать механизм JavaScript, сначала добросовестно переведя spe c text to code (на любом языке, который вы решите использовать для своего движка), , и тогда вам будет разрешено реорганизовать невидимые внутренние компоненты любым удобным для вас способом (например, встроенные функции или разделите их, или организуйте их как вспомогательный класс, или добавьте быстрый путь или кэш, или вообще выверните код наизнанку и т. д. c). Что неудивительно, на самом деле: до тех пор, пока наблюдаемое поведение остается неизменным, любой программе разрешается проводить рефакторинг своих внутренних компонентов. На этом этапе ECMAScript ясно показывает, что «внутренние слоты» действительно гарантированно всегда являются внутренними и не наблюдаемыми.

[[[Get]] и т. Д.] Являются важными внутренними методами. Если движок JavaScript отказывается их реализовывать, как он достигает этой функциональности?

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

Давайте рассмотрим пример Object.getPrototypeOf (). Это API для внутреннего поведения [[GetPrototypeOf]]

Не совсем. Object.getPrototypeOf - это публичная c функция, которая определенным образом работает. Способ, описанный в spe c, заключается в том, что он должен * вести себя так, как если бы был внутренний слот [[GetPrototypeOf]].

Кажется, у вас возникли проблемы с воображением альтернативного пути. Ну, во многих случаях движки, вероятно, захотят иметь реализацию, очень близкую к наличию этих внутренних слотов - возможно, сопоставленную с полями и методами в классе C ++. Но так не должно быть; например, вместо методов класса могут быть свободные функции: GetPrototypeImpl(internal::Object object) вместо internal::Object::GetPrototypeImpl(). Или вместо структуры наследования / иерархии движок может использовать операторы переключения над типами.

Один из наиболее распространенных способов, в которых реализации движков отклоняются от структуры, определенной внутренним значением spe c. слоты, имеющие дополнительные быстрые пути. Как правило, быстрый путь выполняет несколько проверок, чтобы выяснить, применимо ли это, а затем выполняет простой общий случай; если проверка применимости не удалась, она возвращается к более медленной, более полной реализации, которая может быть намного ближе к структуре spe c. Или, может быть, ни одна из функций сама по себе не содержит полного специфического поведения c: у вас может быть GetPrototypeFromRegularObject и GetPrototypeFromProxy плюс обертка, отправляющаяся в правую, и все эти вместе ведут себя как Гипотетическая система spe c имеет слот [[GetPrototypeOf]] на прокси и обычных объектах. Все это совершенно нормально, потому что снаружи вы не видите различий в поведении - все, что вы можете видеть, это Object.getPrototypeOf.

Один конкретный пример быстрого пути - это компилятор. Если бы вы реализовали поведение объекта как (приватные) методы, загружали и вызывали эти методы каждый раз, тогда ваша реализация будет очень медленной. Современные движки компилируют JavaScript функции для байт-кода или даже машинного кода, и этот код будет вести себя так, как если бы вы загрузили и вызвали внутреннюю функцию с заданным поведением , но она (обычно) фактически не будет вызывать какие-либо такие функции. Например, оптимизированный код для доступа array[index] должен состоять только из нескольких машинных инструкций (проверка типа, проверка границ, загрузка памяти), не должно быть вызова задействованного [[Get]].

Другой Очень распространенный пример - типы объектов. В spe c обычно используется такая формулировка, как "если у объекта есть внутренний слот [[StringData]], то ..."; двигатель обычно заменяет это на «если тип объекта - это то, что я выбрал для внутреннего представления строк, тогда ...». Опять же, разница не наблюдается снаружи: строки ведут себя , как если бы они имели a [[StringData]] внутренний слот, но (по крайней мере в V8) у них нет такого слота, у них просто есть соответствующий тип объекта, который идентифицирует их как строки, а объекты со строковым типом знают, где находится их символьная нагрузка, им для этого не требуется никакого специального слота.

Редактировать: забыли упомянуть: см. также https://v8.dev/blog/understanding-ecmascript-part-1 для другого способа объяснить это.

...