Por que arr = é mais rápido que arr = new Array?

Eu corri este código e obtive o resultado abaixo. Eu curioso para saber porque [] é mais rápido?

 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') 
  • usando [] : 299ms
  • usando new : 363ms

Graças a Raynos aqui é uma referência deste código e uma maneira mais possível de definir uma variável.

insira a descrição da imagem aqui

   

Expandindo ainda mais as respostas anteriores …

De uma perspectiva geral de compiladores e desconsiderando otimizações específicas de VM:

Primeiro, passamos pela fase de análise lexical onde nós tokenizamos o código.

Por exemplo, os seguintes tokens podem ser produzidos:

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

Espero que isso forneça uma visualização suficiente para que você possa entender quanto mais (ou menos) processamento é necessário.

  1. Com base nos tokens acima, sabemos que um fato ARRAY_INIT sempre produzirá um array. Nós, portanto, simplesmente criamos um array e o preenchemos. Quanto à ambiguidade, o estágio de análise léxica já distinguiu ARRAY_INIT de um acessador de propriedade de object (por exemplo, obj[foo] ) ou colchetes dentro de strings / literais de regex (por exemplo, “foo [] bar” ou / [] /)

  2. Isso é minúsculo, mas também temos mais tokens com o new Array . Além disso, ainda não está totalmente claro que simplesmente queremos criar um array. Nós vemos o “novo” token, mas “novo” o que? Em seguida, vemos o token IDENTIFIER, que significa que queremos um novo “Array”, mas as VMs JavaScript geralmente não distinguem um token IDENTIFIER e tokens para “objects globais nativos”. Assim sendo…

  3. Temos que procurar a cadeia de escopo cada vez que encontramos um token IDENTIFIER. As VMs Javascript contêm um “object de ativação” para cada contexto de execução que pode conter o object “arguments”, variables ​​definidas localmente, etc. Se não pudermos encontrá-lo no object de ativação, começaremos a pesquisar a cadeia de escopo até atingirmos o escopo global . Se nada for encontrado, lançamos um ReferenceError .

  4. Depois de localizar a declaração da variável, chamamos o construtor. new Array é uma chamada de function implícita e a regra geral é que as chamadas de function são mais lentas durante a execução (por isso compiladores C / C ++ estáticos permitem “inlining de function” – que os mecanismos JS JIT como o SpiderMonkey têm que fazer on-the-fly )

  5. O construtor Array está sobrecarregado. O construtor Array é implementado como código nativo, de modo que ele fornece alguns aprimoramentos de desempenho, mas ainda precisa verificar o tamanho dos argumentos e agir de acordo. Além disso, no caso de apenas um argumento ser fornecido, precisamos verificar o tipo do argumento. new Array (“foo”) produz [“foo”] onde o novo Array (1) produz [indefinido]

Então, para simplificar tudo: com literais de array, a VM sabe que queremos uma matriz; com o new Array , a VM precisa usar ciclos extras de CPU para descobrir o que o new Array realmente faz.

Um possível motivo é que o new Array requer uma pesquisa de nome no Array (você pode ter uma variável com esse nome no escopo), enquanto [] não.

Boa pergunta. O primeiro exemplo é chamado de literal de matriz. É a maneira preferida de criar arrays entre muitos desenvolvedores. Pode ser que a diferença de desempenho seja causada pela verificação dos argumentos da nova chamada Array () e, em seguida, pela criação do object, enquanto o literal cria uma matriz diretamente.

A diferença relativamente pequena no desempenho suporta esse ponto, eu acho. Você poderia fazer o mesmo teste com o object e o literal de object {}.

Isso faria algum sentido

Os literais de objects nos permitem escrever código que suporta muitos resources, mas ainda assim torná-lo relativamente simples para os implementadores do nosso código. Não há necessidade de chamar os construtores diretamente ou manter a ordem correta dos argumentos passados ​​para as funções, etc.

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