Более подробно о предыдущих ответах ...
С точки зрения общих компиляторов и без учета специфичных для ВМ оптимизаций:
Сначала мы проходим фазу лексического анализа, где мы токенизируем код.
Например, могут быть получены следующие токены:
[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)
Надеемся, что это обеспечит вам достаточную визуализацию, чтобы вы могли понять, насколько требуется больше (или меньше) обработки.
Исходя из вышеприведенных токенов, мы знаем, что ARRAY_INIT всегда будет создавать массив.Поэтому мы просто создаем массив и заполняем его.Что касается неоднозначности, то на этапе лексического анализа ARRAY_INIT уже отличался от средства доступа к свойству объекта (например, obj[foo]
) или квадратных скобок внутри литералов строк / регулярных выражений (например, "foo [] bar" или / [] /)
* 1016.* Это незначительно, но у нас также есть больше токенов с new Array
.Кроме того, пока не совсем ясно, что мы просто хотим создать массив.Мы видим «новый» токен, но «новый» что?Затем мы видим токен IDENTIFIER, который означает, что мы хотим новый «массив», но виртуальные машины JavaScript обычно не различают токен IDENTIFIER и токены для «нативных глобальных объектов».Поэтому ...
Мы должны искать цепочку областей действия каждый раз, когда встречаем токен IDENTIFIER.Виртуальные машины Javascript содержат «объект активации» для каждого контекста выполнения, который может содержать объект «аргументы», локально определенные переменные и т. Д. Если мы не можем найти его в объекте активации, мы начинаем искать цепочку областей действия, пока не достигнем глобальной области видимости.,Если ничего не найдено, мы бросаем ReferenceError
.
Как только мы нашли объявление переменной, мы вызываем конструктор.new Array
- это неявный вызов функции, и практическое правило заключается в том, что вызовы функций медленнее во время выполнения (следовательно, статические компиляторы C / C ++ допускают «встраивание функций» - какие механизмы JS JIT, такие как SpiderMonkey, должны делать на месте.fly)
Конструктор Array
перегружен.Конструктор Array реализован в виде собственного кода, поэтому он обеспечивает некоторые улучшения производительности, но ему все равно необходимо проверить длину аргументов и действовать соответствующим образом.Более того, если указан только один аргумент, нам нужно дополнительно проверить тип аргумента.new Array ("foo") создает ["foo"], где new Array (1) создает [undefined]
Итак, чтобы упростить все это: с массивами литералов виртуальная машина знает, что мыхочу массив;с new Array
виртуальная машина должна использовать дополнительные циклы ЦП, чтобы выяснить, что на самом деле new Array
делает.