Почему arr = [] быстрее, чем arr = new Array? - PullRequest
143 голосов
/ 11 сентября 2011

Я запустил этот код и получил следующий результат.Мне интересно знать, почему [] быстрее?

console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')

console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
  • с использованием []: 299 мс
  • с использованием new: 363 мс

Благодаря Raynos здесь есть эталон этого кода и еще один возможный способ определения переменной.

enter image description here

Ответы [ 4 ]

191 голосов
/ 11 сентября 2011

Более подробно о предыдущих ответах ...

С точки зрения общих компиляторов и без учета специфичных для ВМ оптимизаций:

Сначала мы проходим фазу лексического анализа, где мы токенизируем код.

Например, могут быть получены следующие токены:

[]: 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)

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

  1. Исходя из вышеприведенных токенов, мы знаем, что ARRAY_INIT всегда будет создавать массив.Поэтому мы просто создаем массив и заполняем его.Что касается неоднозначности, то на этапе лексического анализа ARRAY_INIT уже отличался от средства доступа к свойству объекта (например, obj[foo]) или квадратных скобок внутри литералов строк / регулярных выражений (например, "foo [] bar" или / [] /)

    * 1016.*
  2. Это незначительно, но у нас также есть больше токенов с new Array.Кроме того, пока не совсем ясно, что мы просто хотим создать массив.Мы видим «новый» токен, но «новый» что?Затем мы видим токен IDENTIFIER, который означает, что мы хотим новый «массив», но виртуальные машины JavaScript обычно не различают токен IDENTIFIER и токены для «нативных глобальных объектов».Поэтому ...

  3. Мы должны искать цепочку областей действия каждый раз, когда встречаем токен IDENTIFIER.Виртуальные машины Javascript содержат «объект активации» для каждого контекста выполнения, который может содержать объект «аргументы», локально определенные переменные и т. Д. Если мы не можем найти его в объекте активации, мы начинаем искать цепочку областей действия, пока не достигнем глобальной области видимости.,Если ничего не найдено, мы бросаем ReferenceError.

  4. Как только мы нашли объявление переменной, мы вызываем конструктор.new Array - это неявный вызов функции, и практическое правило заключается в том, что вызовы функций медленнее во время выполнения (следовательно, статические компиляторы C / C ++ допускают «встраивание функций» - какие механизмы JS JIT, такие как SpiderMonkey, должны делать на месте.fly)

  5. Конструктор Array перегружен.Конструктор Array реализован в виде собственного кода, поэтому он обеспечивает некоторые улучшения производительности, но ему все равно необходимо проверить длину аргументов и действовать соответствующим образом.Более того, если указан только один аргумент, нам нужно дополнительно проверить тип аргумента.new Array ("foo") создает ["foo"], где new Array (1) создает [undefined]

Итак, чтобы упростить все это: с массивами литералов виртуальная машина знает, что мыхочу массив;с new Array виртуальная машина должна использовать дополнительные циклы ЦП, чтобы выяснить, что на самом деле new Array делает.

27 голосов
/ 11 сентября 2011

Одной из возможных причин является то, что new Array требует поиска имени в Array (вы можете иметь переменную с этим именем в области видимости), тогда как [] - нет.

2 голосов
/ 11 сентября 2011

Хороший вопрос.Первый пример называется литералом массива.Это предпочтительный способ создания массивов среди многих разработчиков.Возможно, разница в производительности вызвана проверкой аргументов нового вызова Array () и созданием объекта, в то время как литерал создает массив напрямую.

Относительно небольшая разница в производительности поддерживает эту точку Iсчитать.Кстати, вы можете сделать тот же тест с Object и object literal {}.

1 голос
/ 11 сентября 2011

В этом есть какой-то смысл

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

http://www.dyn -web.com / tutorials / obj_lit.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...