¿Cuál es la diferencia entre "Array ()" y "[]" al declarar una matriz de JavaScript?

841

¿Cuál es la verdadera diferencia entre declarar una matriz como esta:

var myArray = new Array();

y

var myArray = [];
Amr Elgarhy
fuente
[]token: ARRAY_INIT; new Arrayfichas: NEW, IDENTIFIER; new Array()fichas:NEW, IDENTIFIER, CALL
noobninja

Respuestas:

952

Hay una diferencia, pero no hay diferencia en ese ejemplo.

Usando el método más detallado: new Array()tiene una opción adicional en los parámetros: si pasa un número al constructor, obtendrá una matriz de esa longitud:

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

Para ilustrar las diferentes formas de crear una 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

;

Otra diferencia es que cuando se usa new Array()puede establecer el tamaño de la matriz, lo que afecta el tamaño de la pila. Esto puede ser útil si obtiene desbordamientos de pila ( Rendimiento de Array.push vs Array.unshift ), que es lo que sucede cuando el tamaño de la matriz excede el tamaño de la pila, y debe volver a crearse. Entonces, en realidad, dependiendo del caso de uso, puede haber un aumento en el rendimiento cuando se usa new Array()porque puede evitar que ocurra el desbordamiento.

Como se señaló en esta respuesta , en new Array(5)realidad no agregará cinco undefinedelementos a la matriz. Simplemente agrega espacio para cinco elementos. Tenga en cuenta que el uso de Arrayesta manera hace que sea difícil confiar en los array.lengthcálculos.

nickf
fuente
66
Esto está un poco mal. Hay una diferencia muy importante entre el nuevo Array () y [] detallaré en mi respuesta.
coderjoe
30
Pero como se señaló en su respuesta, ¿solo es diferente si está completamente loco y sobrescribe la función Array?
nickf
19
Bueno, la importancia es que el uso del nuevo operador hace que el intérprete tome todo tipo de pasos adicionales para ir al ámbito global, buscar el constructor, llamar al constructor y asignar el resultado ... que en la mayoría de los casos será Una matriz de tiempo de ejecución. Puede evitar la sobrecarga de buscar el constructor global simplemente usando []. Puede parecer pequeño, pero cuando está disparando para obtener un rendimiento casi en tiempo real en su aplicación, puede marcar la diferencia.
coderjoe
55
Hay una gran diferencia de rendimiento: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio
44
Es cierto, pero tampoco necesita punto y coma o saltos de línea en la mayoría de los lugares donde los agrego. Se trata de consistencia y legibilidad. Ya sabes, en mi humilde opinión.
nickf
774

La diferencia entre crear una matriz con la matriz implícita y el constructor de la matriz es sutil pero importante.

Cuando crea una matriz usando

var a = [];

Le está diciendo al intérprete que cree una nueva matriz de tiempo de ejecución. No es necesario ningún procesamiento adicional. Hecho.

Si utiliza:

var a = new Array();

Le estás diciendo al intérprete, quiero llamar al constructor " Array" y generar un objeto. Luego busca a través de su contexto de ejecución para encontrar el constructor al que llamar, y lo llama, creando su matriz.

Puedes pensar "Bueno, esto no importa en absoluto. ¡Son lo mismo!". Lamentablemente no puedes garantizar eso.

Tome el siguiente ejemplo:

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)

En el ejemplo anterior, la primera llamada alertará a 'SPARTA' como era de esperar. El segundo no lo hará. Terminarás viendo indefinido. También notará que b contiene todas las funciones nativas del objeto Array tales como push, donde el otro no.

Si bien puede esperar que esto suceda, solo ilustra el hecho de que []no es lo mismo que new Array().

Probablemente sea mejor usarlo []si sabes que solo quieres una matriz. Tampoco sugiero ir y redefinir Array ...

coderjoe
fuente
157
Bueno, es bueno saberlo, supongo. ¿Qué clase de persona sería sobrescribir la clase matriz, no sé ...
nickf
160
Estás absolutamente en lo correcto. Solo un loco sobrescribiría la clase de matriz. Ahora tómese un momento y considere todo el trabajo adicional que usa el nuevo Array () que hace que el intérprete haga para apoyar a estos locos. Simplemente lo evito todo junto con [].
coderjoe
51
Buen ejemplo del tipo de contaminación global que es posible con JavaScript.
David Snabel-Caunt
8
Vale la pena señalar que el nuevo Array (tamaño) es más rápido que otros métodos posibles que usan la notación []. Fuente: jsperf.com/create-an-array-of-initial-size/2
Marco Luglio
99
Lamentablemente, esa prueba está mal preparada. Está probando una inicialización de una matriz con inicializaciones de matrices seguidas de acceso a la matriz. No hay control que demuestre que los navegadores en realidad preasignan la memoria (lo que la especificación no dice que deben hacer). Si podemos suponer que el acceso a la matriz es constante y la mayor parte del tiempo se dedicará a asignar memoria en ambos ejemplos, entonces [] podría ser preferible si está creando instancias de millones de matrices. jsperf.com/array-instanciation
coderjoe
95

Hay una diferencia importante que ninguna respuesta ha mencionado todavía.

De esto:

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

Puedes pensar que new Array(2) es equivalente a [undefined, undefined], ¡ pero NO lo es!

Probemos con map() :

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

¿Ver? ¡La semántica es totalmente diferente! Entonces, ¿por qué es eso?

De acuerdo con la especificación ES6 22.1.1.2, el trabajo de Array(len)es simplemente crear una nueva matriz cuya propiedad lengthse establece en el argumento leny eso es todo, lo que significa que no hay ninguna elemento real dentro de esta matriz recién creada.

La función map(), de acuerdo con la especificación 22.1.3.15, primero verificaría y HasPropertyluego llamaría a la devolución de llamada, pero resulta que:

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

Y es por eso que no puede esperar que ninguna función iterativa funcione como de costumbre en matrices creadas a partir de new Array(len) .

Por cierto, Safari y Firefox tienen una "impresión" mucho mejor para esta situación:

// 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 ]

Ya he enviado un problema a Chromium y les pido que arreglen esta impresión confusa: https://bugs.chromium.org/p/chromium/issues/detail?id=732021

ACTUALIZACIÓN: Ya está arreglado. Chrome ahora impreso como:

new Array(2)             // (2) [empty × 2]
Hux
fuente
22
La suya es la única respuesta real
Victor
Esto tiene sentido, me topé con una construcción diferente para la que no puedo encontrar referencias documentadas: lo [...Array(2)]que es equivalente [undefined, undefined]desde el punto de vista de los resultados.
Roberto Andrade
Parece que la respuesta a mis comentarios anteriores es "Operador de propagación": javascript.info/rest-parameters-spread-operator
Roberto Andrade
@RobertoAndrade tiene sentido porque el operador de propagación necesitará leer las entradas para que pueda aplicar dicha copia ... y leer el retorno de la ranura vacía undefinedcomo de costumbre.
Hux
51

Por extraño que parezca, new Array(size)es casi 2 veces más rápido que []en Chrome, y casi lo mismo en FF e IE (medido mediante la creación y el llenado de una matriz). Solo importa si conoce el tamaño aproximado de la matriz. Si agrega más elementos que la longitud que ha asignado, se pierde el aumento de rendimiento.

Más exactamente: Array(es una operación rápida de tiempo constante que no asigna memoria, mientras que []es una operación de tiempo lineal que establece el tipo y el valor.

gblazex
fuente
3
Lo probé mucho en Node.js: cuando necesita poner una cierta cantidad de elementos en la matriz, new Array(length)en 0 <= size <= ~ 1000, en tamaño> ~ 1000 victorias[]
glukki
40

Para obtener más información, la siguiente página describe por qué nunca necesita usarnew Array()

Nunca necesita usar new Object()en JavaScript. Utilice el objeto literal en su {} lugar. Del mismo modo, no use new Array(), use la matriz literal en su [] lugar. Las matrices en JavaScript no funcionan como las matrices en Java, y el uso de la sintaxis similar a Java lo confundirá.

No utilice new Number, new Stringo new Boolean. Estas formas producen envoltorios de objetos innecesarios. Simplemente use literales simples en su lugar.

Consulte también los comentarios: el new Array(length)formulario no tiene ningún propósito útil (al menos en las implementaciones actuales de JavaScript).

BarelyFitz
fuente
3
Crockford, también, dice que use [] en lugar de una nueva matriz (). Desafortunadamente, no dice por qué en el artículo vinculado. Supongo que es solo una cuestión de espacio y velocidad. javascript.crockford.com/code.html
Nosredna
44
Crockford no es fanático del uso de la palabra clave "nueva" para crear una nueva instancia de un objeto en Javascript. En las conferencias, ha declarado que cree que crea ambigüedad y que no encaja bien con la herencia de estilo prototipo de Javascript. Se refiere específicamente a los constructores de objetos creados por el usuario, pero dada esa creencia, es fácil ver por qué recomendaría que no lo use también con los elementos integrados cuando hay una sintaxis alternativa.
Alan Storm
@Alan Storm: al menos para Number, String y Boolean, dice "estas formas producen envoltorios de objetos innecesarios", pero supongo que eso no se aplicaría a Array.
BarelyFitz
10

Para comprender mejor []y 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

El resultado anterior es de la consola Google Chrome en Windows 7.

Peter Lee
fuente
44
pero ¿por qué es [] == [] o [] === [] falso?
Anu
55
"Una expresión que compara Objetos solo es verdadera si los operandos hacen referencia al mismo Objeto". (fuente: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
srph
Esta respuesta cherry selecciona ejemplos para implicar que las dos construcciones son idénticas. Otras publicaciones en esta página señalan las diferencias, como Array(3)o new Array(3)no es lo mismo que [3].
ggorlen
8

El primero es la llamada del constructor de objetos predeterminado. Puede usar sus parámetros si lo desea.

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

El segundo le brinda la capacidad de crear una matriz no vacía:

var array = [1, 2, 3]; // this array will contain numbers 1, 2, 3.
Bogdan Gusiev
fuente
1
Puede hacer lo mismo con el constructor detallado: var array = new Array (1, 2, 3);
nickf
Entonces, supongo que puedes hacerlo var array = [5]usando los corchetes pero sin usar el constructor, ya var array = Array(5)que forma una matriz vacía de 5 elementos.
cdmckay
cdmckay: eso es incorrecto. var a = [5] sería una matriz con un solo elemento: el número cinco.
BarelyFitz
2
@BarelyFitz: Eso es lo que dije. En la respuesta de Bogdans, dice que la llamada del constructor no se puede usar para inicializar una matriz, pero estaba equivocado. Mi comentario fue simplemente para aclarar que no se puede usar la llamada del constructor para inicializar una matriz de un solo elemento.
cdmckay
1
@cdmckay: lo siento, entendí mal tu comentario. Para aclarar: nueva matriz (arg): si arg es numérico, esto crea una matriz vacía con longitud = arg; nueva matriz (arg1, arg2): crea una nueva matriz e inicializa los elementos de la matriz. Entonces, si desea crear una matriz con un elemento numérico como [5], no puede hacerlo utilizando la nueva matriz (5). Pero realmente nunca deberías usar el nuevo Array (), así que este es un punto discutible.
BarelyFitz
5

Puedo explicar de una manera más específica comenzando con este ejemplo que se basa en el buen 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);

Acabo de agregar otro valor a las matrices e hice cuatro alertas: la primera y la segunda son para darnos el valor almacenado en cada matriz, para estar seguros de los valores. ¡Volverán lo mismo! Ahora prueba el tercero, devuelve falso, eso es porque

JS trata la prueba1 como una VARIABLE con un tipo de datos de matriz , y trata la prueba2 como un OBJETO con la funcionalidad de una matriz , y aquí hay algunas pequeñas diferencias.

La primera diferencia es que cuando llamamos a test1, llama a una variable sin pensar, ¡simplemente devuelve los valores almacenados en esta variable sin tener en cuenta su tipo de datos! Pero, cuando llamamos a test2, llama a la función Array () y luego almacena nuestros valores "Empujados" en su propiedad "Valor" , y lo mismo ocurre cuando alertamos a test2, devuelve el "Valor" propiedad del objeto de matriz.

Entonces, cuando verificamos si test1 es igual a test2, por supuesto, nunca devolverán verdadero, uno es una función y el otro es una variable (con un tipo de matriz), ¡incluso si tienen el mismo valor!

Para estar seguro de eso, intente la 4ta alerta, con el valor agregado; Volverá cierto. En este caso, le decimos a JS "Sin tener en cuenta el tipo de contenedor, ya sea funcional o variable, compare los valores almacenados en cada contenedor y díganos lo que ha visto". eso es exactamente lo que pasa.

Espero haber dicho claramente la idea detrás de eso, y lo siento por mi mal inglés.

Kholio
fuente
19
Es sorprendente que se haya votado tan absurdo tan completo y absoluto. La comparación entre las matrices será falsa, no importa cómo las haga, ya que compara la identidad del objeto y son objetos diferentes. Las matrices no tienen propiedades de valor. []y new Array()es idéntico .valueserá undefineden ambos casos, y compararlos siempre será falso.
slikts
De acuerdo, esta respuesta no tiene sentido y no muestra nada. No hay tal cosa como array.value. y ambos typeof []y typeof new Array()regreso object. Es una de las razones por las que hay una función llamadaArray.isArray
gman
4

No hay diferencia cuando inicializa la matriz sin ninguna longitud. Entonces var a = []yvar b = new Array() es lo mismo.

Pero si inicializa la matriz con una longitud similar var b = new Array(1);, establecerá la longitud del objeto de la matriz en 1. Por lo tanto, es equivalente a var b = []; b.length=1; .

Esto será problemático cada vez que haga array_object.push, agregará un elemento después del último elemento y aumentará la longitud.

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
fuente
3

El primero es la llamada al constructor de objetos predeterminado. Se usa principalmente para valores dinámicos.

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

la segunda matriz se usa al crear valores estáticos

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

No hay una gran diferencia, básicamente hacen lo mismo pero haciéndolos de diferentes maneras, pero sigue leyendo, mira esta declaración en W3C:

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

y

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

Los dos ejemplos anteriores hacen exactamente lo mismo. No es necesario usar new Array ().
Por simplicidad, legibilidad y velocidad de ejecución, use el primero (el método literal de matriz).

Pero al mismo tiempo, crear una nueva matriz utilizando la new Arraysintaxis se considera una mala práctica:

Evitar nueva matriz ()

No es necesario utilizar el nuevo constructor de matrices incorporado de JavaScript, Array ().
Use [] en su lugar.
Estas dos declaraciones diferentes crean una nueva matriz vacía llamada puntos:

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

Estas dos declaraciones diferentes crean una nueva matriz que contiene 6 números:

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

La nueva palabra clave solo complica el código. También puede producir algunos resultados inesperados:

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

¿Qué pasa si elimino uno de los elementos?

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

Así que, básicamente, no se considera como la mejor práctica, también hay una pequeña diferencia allí, puede pasar la longitud de new Array(length)esta manera, lo que tampoco es una forma recomendada.

Alireza
fuente
Hola Alireza, ¿estas son copiadas y pegadas de algún lado? Agregue un enlace a la página desde donde se copia el texto. Consulte esta página del centro de ayuda para obtener más información. Gracias.
Pang
Útil paranew Array(40).fill(123)
gman
2

La diferencia de usar

var arr = new Array(size);

O

arr = [];
arr.length = size;

Como se ha discutido lo suficiente en esta pregunta.

Me gustaría agregar el problema de la velocidad, la forma más rápida actual , engoogle chrome es la segunda.

Pero presta atención, estas cosas tienden a cambiar mucho con las actualizaciones. Además, el tiempo de ejecución diferirá entre los diferentes navegadores.

Por ejemplo, la segunda opción que mencioné, se ejecuta a 2 millones [ops / segundo] en adelante chrome, pero si la probarasmozilla dev. obtendría una tasa sorprendentemente más alta de 23 millones.

De todos modos, te sugiero que lo revises, de vez en cuando, en diferentes navegadores (y máquinas), usando el sitio como tal

Meir Elad
fuente
2

Como sé, la diferencia puede encontrar el segmento (u otras funciones de Array) como el código1. Y el código2 muestra Array y sus instancias :

código1:

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

código2:

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

conclusión:

como puede ver []y new Array()crear una nueva instancia de Array. Y todos obtienen las funciones prototipo deArray.prototype

Son simplemente una instancia diferente de Array. Esto explica por qué [] != []

:)

sammy
fuente
2

He incurrido en un comportamiento extraño usando [].

Tenemos "clases" de modelo con campos inicializados a algún valor. P.ej:

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

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

Descubrí que cuando se inicializan los campos, []todos los objetos Modelo los compartirían. Hacer cambios a uno afecta a todos los demás.

Esto no sucede inicializándolos con new Array(). Lo mismo para la inicialización de objetos ( {}vs nuevo Object())

TBH No estoy seguro si es un problema con el marco que estábamos usando ( Dojo )

algiogia
fuente
2

Hay más en esto de lo que parece. La mayoría de las otras respuestas son correctas, PERO TAMBIÉN ...

new Array(n)

  • Permite que el motor reasigne espacio para nelementos
  • Optimizado para la creación de matrices
  • La matriz creada está marcada como dispersa, que tiene las operaciones de matriz de menor rendimiento, eso se debe a que cada acceso al índice tiene que verificar los límites, ver si existe el valor y recorrer la cadena del prototipo
  • Si la matriz está marcada como dispersa, no hay vuelta atrás (al menos en V8), siempre será más lenta durante su vida útil, incluso si la llena con contenido (matriz empaquetada) 1 ms o 2 horas más tarde, no importa

[1, 2, 3] || []

  • La matriz creada está marcada como empaquetada (a menos que use deleteo [1,,3]sintaxis)
  • Optimizado para la matriz operaciones ( for .., forEach, map, etc.)
  • El motor necesita reasignar el espacio a medida que crece la matriz

Esto probablemente no es el caso para los navegadores más antiguas versiones / navegadores.

Solo
fuente
-2

He encontrado una diferencia entre las dos construcciones que me han picado bastante.

Digamos que tengo:

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

En la vida real, si hago esto:

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

Lo que termino con es esto:

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

No sé qué se supone que sucederá en la especificación del lenguaje, pero si quiero que mis dos objetos tengan matrices de propiedades únicas en mis objetos, tengo que usarlos new Array().

Bucky
fuente
Este JSFiddle muestra que la salida es lo que esperaría con el literal de matriz []y el new Array()constructor, lo que da como resultado un elemento por matriz por propiedad. Debe tener algo más en su código para terminar con el resultado que muestra arriba.
gfullam
Bucky, eso no me pasa, en ningún navegador. Para obtener ese comportamiento, tendría que hacer algo como esto: var property1static=[]; function MyClass(){ this.property1=property1static; this.property2=new Array(); };
Dave Burton el
-3

El uso del constructor Array crea una nueva matriz de la longitud deseada y llena cada uno de los índices con indefinido, la matriz asignada a una variable crea los índices para los que le da información.

Timothy Trousdale
fuente
1
No, la matriz NO está poblada, no hay índices / claves dentro. Por ejemplo .forEach no funcionaría.
CFrei