Qual é a diferença entre "Array ()" e "[]" ao declarar uma matriz JavaScript?

841

Qual é a diferença real entre declarar uma matriz como esta:

var myArray = new Array();

e

var myArray = [];
Amr Elgarhy
fonte
[]token: ARRAY_INIT; new Arrayfichas: NEW, IDENTIFIER; new Array()fichas:NEW, IDENTIFIER, CALL
noobninja 18/02/19

Respostas:

951

Há uma diferença, mas não há diferença nesse exemplo.

Usando o método mais detalhado: new Array()tem uma opção extra nos parâmetros: se você passar um número para o construtor, obterá uma matriz desse comprimento:

x = new Array(5);
alert(x.length); // 5

Para ilustrar as diferentes maneiras de criar uma matriz:

var a = [],            // these are the same
    b = new Array(),   // a and b are arrays with length 0

    c = ['foo', 'bar'],           // these are the same
    d = new Array('foo', 'bar'),  // c and d are arrays with 2 strings

    // these are different:
    e = [3]             // e.length == 1, e[0] == 3
    f = new Array(3),   // f.length == 3, f[0] == undefined

;

Outra diferença é que, ao usar, new Array()você pode definir o tamanho da matriz, o que afeta o tamanho da pilha. Isso pode ser útil se você estiver recebendo estouros de pilha ( Desempenho de Array.push vs Array.unshift ), que é o que acontece quando o tamanho da matriz excede o tamanho da pilha e precisa ser recriada. Portanto, dependendo do caso de uso, pode haver um aumento de desempenho ao usar, new Array()pois você pode impedir que o estouro aconteça.

Como apontado nesta resposta , new Array(5)na verdade , não adicionamos cinco undefineditens à matriz. Simplesmente adiciona espaço para cinco itens. Esteja ciente de que o uso Arraydessa maneira dificulta a utilização array.lengthde cálculos.

nickf
fonte
66
Isso está um pouco errado. Há uma diferença muito importante entre o novo Array () e [] que vou elaborar na minha resposta.
Coderjoe 13/08/09
30
Mas, como observado na sua resposta, só será diferente se você estiver completamente louco e sobrescrever a função Array ..?
nickf
19
Bem, a importância é que o uso do novo operador faz com que o intérprete tome todos os tipos de etapas extras para ir para o escopo global, procure o construtor, chame o construtor e atribua o resultado ... que, na maioria das vezes, será uma matriz de tempo de execução. Você pode evitar a sobrecarga de procurar o construtor global usando apenas []. Pode parecer pequeno, mas quando você está gravando para um desempenho quase em tempo real no seu aplicativo, pode fazer a diferença.
Coderjoe 14/08/09
5
Há uma enorme diferença de desempenho: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio
4
É verdade, mas você também não precisa de ponto e vírgula ou quebras de linha na maioria dos lugares em que os adiciono. É sobre consistência e legibilidade. Você sabe, IMHO.
nickf
774

A diferença entre criar uma matriz com a matriz implícita e o construtor da matriz é sutil, mas importante.

Quando você cria uma matriz usando

var a = [];

Você está dizendo ao intérprete para criar uma nova matriz de tempo de execução. Não é necessário processamento extra. Feito.

Se você usar:

var a = new Array();

Você está dizendo ao intérprete, eu quero chamar o construtor "Array " e gerar um objeto. Ele então pesquisa seu contexto de execução para encontrar o construtor a ser chamado, e o chama, criando sua matriz.

Você pode pensar "Bem, isso não importa. Eles são iguais!". Infelizmente você não pode garantir isso.

Veja o seguinte exemplo:

function Array() {
    this.is = 'SPARTA';
}

var a = new Array();
var b = [];

alert(a.is);  // => 'SPARTA'
alert(b.is);  // => undefined
a.push('Woa'); // => TypeError: a.push is not a function
b.push('Woa'); // => 1 (OK)

No exemplo acima, a primeira chamada alertará 'SPARTA' conforme o esperado. O segundo não. Você acabará vendo indefinido. Você também observará que b contém todas as funções nativas do objeto Array, como push, onde o outro não.

Embora você possa esperar que isso aconteça, apenas ilustra o fato de que []não é o mesmo new Array().

Provavelmente é melhor usar apenas []se você sabe que deseja apenas uma matriz. Eu também não sugiro dar uma volta e redefinir Array ...

coderjoe
fonte
157
Bem, é bom saber, suponho. Que tipo de pessoa iria substituir a classe array, eu não sei ...
nickf
160
Você está absolutamente correto. Somente um louco substituiria a classe array. Agora, dedique um momento e considere todo o trabalho extra que o novo Array () faz o intérprete fazer para apoiar esses loucos. Eu apenas evito tudo junto com [].
Coderjoe 14/08/09
51
Bom exemplo do tipo de poluição global possível com JavaScript.
David Snabel-Caunt
8
Vale ressaltar que a nova matriz (tamanho) é mais rápida que outros métodos possíveis usando a notação []. Fonte: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio
9
Infelizmente esse teste está preparado de maneira inadequada. Está testando uma inicialização de uma matriz com inicializações de matrizes seguidas pelo acesso à matriz. Não há controle para provar que os navegadores estão realmente pré-alocando a memória (o que a especificação não diz que deve fazer). Se pudermos supor que o acesso à matriz seja constante e a maior parte do tempo seja gasta alocando memória nos dois exemplos, [] poderá ser preferível se você estiver instanciando milhões de matrizes. jsperf.com/array-instanciation
coderjoe
95

Há uma diferença importante que nenhuma resposta mencionou ainda.

Disto:

new Array(2).length           // 2
new Array(2)[0] === undefined // true
new Array(2)[1] === undefined // true

Você pode pensar que new Array(2)é equivalente a [undefined, undefined], mas NÃO é!

Vamos tentar com map():

[undefined, undefined].map(e => 1)  // [1, 1]
new Array(2).map(e => 1)            // "(2) [undefined × 2]" in Chrome

Vejo? A semântica é totalmente diferente! Então porque é isso?

De acordo com a ES6 Spec 22.1.1.2, o trabalho de Array(len)apenas criar uma nova matriz cuja propriedade lengthestá definida como argumento lene é isso, significa que não há nenhum elemento real dentro dessa nova matriz criada.

A função map(), de acordo com a especificação 22.1.3.15, primeiro verifica e HasPropertydepois chama o retorno de chamada, mas acontece que:

new Array(2).hasOwnProperty(0) // false
[undefined, undefined].hasOwnProperty(0) // true

E é por isso que você não pode esperar nenhuma função de iteração funcionando normalmente em matrizes criadas a partir de new Array(len) .

BTW, Safari e Firefox têm uma "impressão" muito melhor para esta situação:

// Safari
new Array(2)             // [](2)
new Array(2).map(e => 1) // [](2) 
[undefined, undefined]   // [undefined, undefined] (2) 

// Firefox
new Array(2)             // Array [ <2 empty slots> ]
new Array(2).map(e => 1) // Array [ <2 empty slots> ]
[undefined, undefined]   // Array [ undefined, undefined ]

Eu já enviei um problema ao Chromium e solicite a correção desta impressão confusa: https://bugs.chromium.org/p/chromium/issues/detail?id=732021

UPDATE: já está consertado. Chrome agora impresso como:

new Array(2)             // (2) [empty × 2]
Hux
fonte
22
O seu é a única resposta real
Victor
Isso faz sentido, acabei de me deparar com uma construção diferente para a [...Array(2)]qual não consigo encontrar referências documentadas: o que equivale ao [undefined, undefined]ponto de vista dos resultados.
Roberto Andrade
Parece que a resposta aos meus comentários anteriores é "operador Spread": javascript.info/rest-parameters-spread-operator
Roberto Andrade
@RobertoAndrade que faz sentido, porque o operador spread precisará ler as entradas para que possa aplicar essa cópia ... e ler o retorno do slot vazio, undefinedcomo de costume.
Hux
51

Curiosamente, new Array(size)é quase duas vezes mais rápido que []no Chrome e quase o mesmo no FF e no IE (medido pela criação e preenchimento de uma matriz). Só importa se você souber o tamanho aproximado da matriz. Se você adicionar mais itens do que o tamanho especificado, o aumento de desempenho será perdido.

Mais precisamente: Array(é uma operação rápida de tempo constante que não aloca memória, enquanto que []é uma operação linear de tempo que define o tipo e o valor.

gblazex
fonte
3
Eu testei-o muito em Node.js: quando você precisa colocar alguma quantidade de itens na matriz, new Array(length)em 0 <= tamanho <= ~ 1000, em tamanho> ~ 1000 vitórias[]
glukki
1
verifique este stackoverflow.com/questions/7375120/…
Xsmael 16/09
40

Para obter mais informações, a página a seguir descreve por que você nunca precisa usarnew Array()

Você nunca precisa usar o new Object()JavaScript. Use o objeto literal em seu {} lugar. Da mesma forma, não use new Array(), use a matriz literal [] . Matrizes em JavaScript não funcionam como as matrizes em Java, e o uso da sintaxe semelhante a Java confunde você.

Não use new Number, new Stringou new Boolean. Esses formulários produzem invólucros de objetos desnecessários. Basta usar literais simples.

Verifique também os comentários - o new Array(length)formulário não serve a nenhum propósito útil (pelo menos nas implementações atuais de JavaScript).

BarelyFitz
fonte
3
Crockford, também, diz usar [] ao invés de novo Array (). Infelizmente, ele não diz o porquê no artigo vinculado. Presumo que seja apenas uma questão de espaço e velocidade. javascript.crockford.com/code.html
Nosredna
4
Crockford não gosta de usar a palavra-chave "new" para criar uma nova instância de um objeto em Javascript. Nas palestras que ele afirmou, acredita que isso cria ambiguidade e não se encaixa bem na herança de estilo de protótipo do Javascript. Ele está se referindo especificamente aos construtores de objetos criados pelo usuário, mas, considerando essa crença, é fácil ver por que ele recomendaria que você não o usasse também com os built-ins quando há uma sintaxe alternativa.
Alan Storm
@ Alan Storm: pelo menos para Number, String e Boolean, ele diz que "esses formulários produzem invólucros de objetos desnecessários", mas acho que isso não se aplicaria ao Array.
BarelyFitz
10

Para melhor entender []e new Array():

> []
  []
> new Array()
  []
> [] == []
  false
> [] === []
  false
> new Array() == new Array()
  false
> new Array() === new Array()
  false
> typeof ([])
  "object"
> typeof (new Array())
  "object"
> [] === new Array()
  false
> [] == new Array()
  false

O resultado acima é do console do Google Chrome no Windows 7.

Peter Lee
fonte
4
mas por que [] == [] ou [] === [] falso?
Anu
5
"Uma expressão comparando Objetos só é verdadeira se os operandos fizerem referência ao mesmo Objeto." (fonte: developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/… )
srph
Essa resposta escolhe exemplos que sugerem que as duas construções são idênticas. Outras postagens nesta página apontam as diferenças, como Array(3)ounew Array(3) não são as mesmas [3].
ggorlen
8

O primeiro é a chamada do construtor de objeto padrão. Você pode usar os parâmetros, se quiser.

var array = new Array(5); //initialize with default length 5

O segundo oferece a capacidade de criar uma matriz não vazia:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.
Bogdan Gusiev
fonte
1
Você pode fazer o mesmo com o construtor detalhado: var array = new Array (1, 2, 3);
nickf
Então eu acho que você pode var array = [5]usar colchetes, mas não o construtor, pois var array = Array(5)cria uma matriz vazia de 5 elementos.
Cdmckay 31/05/09
cdmckay - isso está incorreto. var a = [5] seria uma matriz com um único item - o número cinco.
BarelyFitz
2
@ BarelyFitz: Foi o que eu disse. Na resposta de Bogdans, ele diz que a chamada do construtor não pode ser usada para inicializar uma matriz, mas ele estava errado. Meu comentário foi apenas para esclarecer que você não pode usar a chamada de construtor para inicializar uma matriz de um único elemento.
Cdmckay 31/05/09
1
@cdmckay: desculpe, eu não entendi o seu comentário. Para esclarecer: new Array (arg) - se arg for numérico, isso cria uma matriz vazia com length = arg; nova matriz (arg1, arg2) - cria uma nova matriz e inicializa os elementos da matriz. Portanto, se você deseja criar uma matriz com um elemento numérico como [5], não pode fazê-lo usando a nova matriz (5). Mas, na verdade, você nunca deve usar o novo Array (), portanto esse é um ponto discutível.
BarelyFitz
5

Eu posso explicar de uma maneira mais específica, começando com este exemplo, baseado no bom exemplo de Fredrik.

var test1 = [];
test1.push("value");
test1.push("value2");

var test2 = new Array();
test2.push("value");
test2.push("value2");

alert(test1);
alert(test2);
alert(test1 == test2);
alert(test1.value == test2.value);

Acabei de adicionar outro valor às matrizes e fiz quatro alertas: O primeiro e o segundo devem nos fornecer o valor armazenado em cada matriz, para ter certeza dos valores. Eles retornarão o mesmo! Agora tente o terceiro, ele retorna falso, é porque

JS trata test1 como uma variável com um tipo de dados de matriz , e trata test2 como um objeto com a funcionalidade de uma matriz , e há algumas pequenas diferenças aqui.

A primeira diferença é que quando chamamos test1, ele chama uma variável sem pensar, apenas retorna os valores que são armazenados nessa variável, independentemente do seu tipo de dados! Mas, quando chamamos test2, ele chama a função Array () e, em seguida, armazena nossos valores "Pushed" em sua propriedade "Value" , e o mesmo acontece quando alertamos test2, retornando o "Value" propriedade do objeto de matriz.

Portanto, quando verificamos se test1 é igual a test2, é claro que eles nunca retornarão true, uma é uma função e a outra é uma variável (com um tipo de array), mesmo que tenham o mesmo valor!

Para ter certeza, tente o quarto alerta, com o valor. Adicionado a ele; retornará verdadeiro. Nesse caso, dizemos ao JS "Independentemente do tipo do contêiner, seja ele função ou variável, compare os valores armazenados em cada contêiner e conte-nos o que viu!" é exatamente o que acontece.

Espero ter dito claramente a idéia por trás disso e desculpe-me pelo meu inglês ruim.

Kholio
fonte
19
É incrível que esse absurdo completo e absoluto tenha sido votado. A comparação entre as matrizes será falsa, não importa como você as faça, porque compara a identidade do objeto e elas são objetos diferentes. Matrizes não possuem propriedade de valor. []e new Array()é idêntico; .valueserá undefinedem ambos os casos, e compará-los sempre será falso.
slikts
Concordado, esta resposta não faz sentido e não mostra nada. Não existe tal coisa array.value. e ambos typeof []e typeof new Array()retornar object. É uma das razões pelas quais existe uma função chamadaArray.isArray
gman
4

Não há diferença quando você inicializa a matriz sem nenhum comprimento. Então var a = []& var b = new Array()é o mesmo.

Mas se você inicializar a matriz com comprimento igual var b = new Array(1);, ele definirá o comprimento do objeto da matriz como 1. Portanto, é equivalente a var b = []; b.length=1;.

Isso será problemático sempre que você fizer o array_object.push, ele adicionará item após o último elemento e aumentará o comprimento.

var b = new Array(1);
b.push("hello world");
console.log(b.length); // print 2

vs

var v = [];
a.push("hello world");
console.log(b.length); // print 1
Aniruddha
fonte
3

O primeiro é o construtor de objeto padrão call.mostly usado para valores dinâmicos.

var array = new Array(length); //initialize with default length

a segunda matriz é usada ao criar valores estáticos

var array = [red, green, blue, yellow, white]; // this array will contain values.
Parth Raval
fonte
3

Não há grande diferença, eles basicamente fazem a mesma coisa, mas de maneiras diferentes, mas continue lendo, veja esta declaração no W3C:

var cars = ["Saab", "Volvo","BMW"];

e

var cars = new Array("Saab", "Volvo", "BMW");

Os dois exemplos acima fazem exatamente o mesmo. Não é necessário usar o novo Array ().
Para simplicidade, legibilidade e velocidade de execução, use o primeiro (o método literal do array).

Mas, ao mesmo tempo, criar uma nova matriz usando a new Arraysintaxe considerada uma má prática:

Evitar nova matriz ()

Não há necessidade de usar o construtor de matriz interno do JavaScript new Array ().
Use [].
Essas duas instruções diferentes criam uma nova matriz vazia denominada points:

var points = new Array();         // Bad
var points = [];                  // Good 

Essas duas instruções diferentes criam uma nova matriz contendo 6 números:

var points = new Array(40, 100, 1, 5, 25, 10); // Bad    
var points = [40, 100, 1, 5, 25, 10];          // Good

A nova palavra-chave complica apenas o código. Também pode produzir alguns resultados inesperados:

var points = new Array(40, 100);  // Creates an array with two elements (40 and 100)

E se eu remover um dos elementos?

var points = new Array(40);       // Creates an array with 40 undefined elements !!!!!

Portanto, basicamente não é considerada a melhor prática, também há uma pequena diferença, é possível passar o tempo para new Array(length)isso, o que também não é uma maneira recomendada.

Alireza
fonte
Oi Alireza, estas são copiadas e coladas de algum lugar? Por favor, adicione um link para a página de onde o texto é copiado. Consulte esta página da Central de Ajuda para obter detalhes. Obrigado.
Pang
Útil paranew Array(40).fill(123)
gman
2

A diferença de usar

var arr = new Array(size);

Ou

arr = [];
arr.length = size;

Como já foi discutido o suficiente nesta questão.

Gostaria de acrescentar a questão da velocidade - a maneira mais rápida atualgoogle chrome é a segunda.

Mas preste atenção, essas coisas tendem a mudar muito com as atualizações. Além disso, o tempo de execução será diferente entre os diferentes navegadores.

Por exemplo - a segunda opção que mencionei, é executada em 2 milhões [ops / segundo] chrome, mas se você tentarmozilla dev. obterá uma taxa surpreendentemente maior de 23 milhões.

De qualquer forma, sugiro que você verifique, de vez em quando, em diferentes navegadores (e máquinas), usando o site como tal

Meir Elad
fonte
2

Como eu sei a diferença, você pode encontrar a fatia (ou as outras funções do Array) como code1 .e code2 show u Array e suas instâncias :

code1:

[].slice; // find slice here
var arr = new Array();
arr.slice // find slice here
Array.prototype.slice // find slice here

code2:

[].__proto__ == Array.prototype; // true
var arr = new Array();
arr.__proto__ == Array.prototype; // true

conclusão:

como você pode ver []e new Array()criar uma nova instância de Array. E todas elas obtêm as funções de protótipo deArray.prototype

Eles são apenas instâncias diferentes de Array. Então, isso explica por que [] != []

:)

sammy
fonte
2

Eu incorri em um comportamento estranho usando [].

Temos Model "classes" com campos inicializados com algum valor. Por exemplo:

require([
  "dojo/_base/declare",
  "dijit/_WidgetBase",
], function(declare, parser, ready, _WidgetBase){

   declare("MyWidget", [_WidgetBase], {
     field1: [],
     field2: "",
     function1: function(),
     function2: function()
   });    
});

Descobri que quando os campos são inicializados [], eles seriam compartilhados por todos os objetos Model. Fazer alterações em um afeta todos os outros.

Isso não acontece inicializando-os com new Array(). O mesmo para a inicialização de objetos ( {}vs novo Object())

TBH Não tenho certeza se é um problema com a estrutura que estávamos usando ( Dojo )

algiogia
fonte
2

Há mais do que aparenta. A maioria das outras respostas está correta, MAS TAMBÉM ..

new Array(n)

  • Permite que o mecanismo realoque espaço para nelementos
  • Otimizado para criação de array
  • A matriz criada é marcada como esparsa, com as operações de matriz com menos desempenho, porque cada acesso ao índice deve verificar limites, ver se existe valor e percorrer a cadeia de protótipos
  • Se a matriz estiver marcada como esparsa, não há caminho de volta (pelo menos na V8), sempre será mais lenta durante sua vida útil, mesmo que você a preencha com conteúdo (matriz compactada) 1ms ou 2 horas depois, não importa

[1, 2, 3] || []

  • A matriz criada é marcada como compactada (a menos que você use deleteou [1,,3]sintaxe)
  • Optimizada para matriz operações ( for .., forEach, map, etc)
  • O mecanismo precisa realocar espaço à medida que a matriz cresce

Este provavelmente não é o caso para mais antigas de navegadores versões / navegadores.


fonte
-2

Eu encontrei uma diferença entre as duas construções que me morderam bastante.

Digamos que eu tenho:

function MyClass(){
  this.property1=[];
  this.property2=new Array();
};
var MyObject1=new MyClass();
var MyObject2=new MyClass();

Na vida real, se eu fizer isso:

MyObject1.property1.push('a');
MyObject1.property2.push('b');
MyObject2.property1.push('c');
MyObject2.property2.push('d');

O que eu acabo com é o seguinte:

MyObject1.property1=['a','c']
MyObject1.property2=['b']
MyObject2.property1=['a','c']
MyObject2.property2=['d']

Eu não sei o que a especificação da linguagem diz que deve acontecer, mas se eu quiser que meus dois objetos tenham matrizes de propriedades exclusivas em meus objetos, eu tenho que usá-lo new Array().

Bucky
fonte
Esse JSFiddle mostra que a saída é o que você esperaria com o literal []e o new Array()construtor da matriz, resultando em um item por matriz por propriedade. Você deve ter algo mais acontecendo no seu código para terminar com o resultado mostrado acima.
Gfullam # 24/15
Bucky, isso não acontece para mim, em nenhum navegador. Para obter esse comportamento que você teria que fazer algo como isto: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Dave Burton
-3

O uso do construtor Array cria uma nova matriz com o comprimento desejado e preenche cada um dos índices com indefinido; a matriz atribuída a uma variável cria os índices para os quais você fornece informações.

Timothy Trousdale
fonte
1
Não, o array NÃO é preenchido, não há índices / chaves dentro. Por exemplo .forEach não funcionaria.
precisa saber é o seguinte