Expandindo ainda mais as respostas anteriores ...
De uma perspectiva geral dos compiladores e desconsiderando as otimizações específicas da VM:
Primeiro, passamos pela fase de análise lexical em que tokenizamos o código.
A título de 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 ofereça uma visualização suficiente para que você possa entender quanto mais (ou menos) processamento é necessário.
Com base nos tokens acima, sabemos que ARRAY_INIT sempre produzirá uma matriz. Portanto, simplesmente criamos uma matriz e a preenchemos. Quanto à ambiguidade, o estágio de análise lexical já distinguiu ARRAY_INIT de um acessador de propriedade de objeto (por exemplo obj[foo]
) ou colchetes dentro de strings / regex literais (por exemplo, "foo [] bar" ou / [] /)
Isso é minúsculo, mas também temos mais tokens new Array
. Além disso, ainda não está totalmente claro que simplesmente queremos criar uma matriz. Vemos o "novo" token, mas "novo" o que? Em seguida, vemos o token IDENTIFIER, o que significa que queremos uma nova "matriz", mas as VMs do JavaScript geralmente não distinguem um token e tokens IDENTIFIER para "objetos globais nativos". Portanto...
Temos que procurar a cadeia de escopo sempre que encontrarmos um token IDENTIFIER. As VMs Javascript contêm um "Objeto de ativação" para cada contexto de execução que pode conter o objeto "argumentos", variáveis definidas localmente etc. Se não pudermos encontrá-lo no objeto Ativação, começaremos a procurar a cadeia de escopo até atingir o escopo global . Se nada for encontrado, jogamos a ReferenceError
.
Depois de localizar a declaração da variável, chamamos o construtor. new Array
é uma chamada de função implícita, e a regra geral é que as chamadas de função são mais lentas durante a execução (por isso, os compiladores estáticos de C / C ++ permitem a "função embutida" - que mecanismos JS JIT, como o SpiderMonkey, precisam fazer on-the-fly)
O Array
construtor está sobrecarregado. O construtor Array é implementado como código nativo, portanto fornece alguns aprimoramentos de desempenho, mas ainda precisa verificar o comprimento dos argumentos e agir de acordo. Além disso, no caso de apenas um argumento ser fornecido, precisamos verificar ainda mais o tipo do argumento. new Array ("foo") produz ["foo"] onde, como new Array (1) produz [indefinido]
Então, para simplificar tudo: com literais de matriz, a VM sabe que queremos uma matriz; com new Array
, a VM precisa usar ciclos extras de CPU para descobrir o que new Array
realmente faz.