2012-06-29 9 views
20

considerar:Los valores no definidos en Array inicializador (LEN)

var a = Array(3); 
var b = [undefined,undefined,undefined]; 

¿Cuál es la razón por la que a.map y b.map producen resultados diferentes?

a.map(function(){ return 0; }); //produces -> [undefined,undefined,undefined] 
b.map(function(){ return 0; }); //produces -> [0,0,0] 
+1

relacionadas: echa un vistazo a lo que sucede si se establece 'b.length = 5;' antes de ejecutar el 'map':' [0, 0, 0, indefinido, indefinido] ' – apsillers

Respuesta

23

El constructor de la matriz crea una matriz con la longitud especificada. Hace no crear las claves. La función de devolución de llamada de Array.prototype.map solo se ejecuta para los elementos en la lista.
Es decir, todos los valores que están asociados con una tecla (número entero) 0 ≤ i < longitud.

  • Array(3) tiene teclas de cero, por lo .map 's de devolución de llamada no se dispara.
  • [void 0, void 0, void 0] tiene tres teclas, para las cuales se ejecuta la función de devolución de llamada.

    Array(3).hasOwnProperty(0);     // false 
    [void 0, void 0, void 0].hasOwnProperty(0); // true 
    

La especificación y su polyfill se mencionan en MDN. En la línea 47, if (k in O) { muestra que las claves no existentes no son tratadas por la función de devolución de llamada.

+1

En realidad, mapa debe iterar no sobre las teclas, sino sobre la secuencia de valores 0..array.length-1 –

+0

@ panda-34 Saltar teclas entre 0 y n es similar a caminar sobre las teclas numéricas. Pero está en lo correcto, hablando en sentido estricto, debería haber dicho tal;) –

+0

@RobW ¿Podemos suponer, que 'Array (3)' no * realmente asigna memoria * para almacenar '3' elementos, cuyos valores son' undefined' y simplemente establece la propiedad 'length' en' 3', ¿no es así? – Engineer

4

a es una matriz vacía que no tiene elementos, por lo que un mapa de función produce matriz vacía sin elementos (por especificación, mapa produce resultados sólo si [[hasProperty]] es cierto.)b es una matriz de tres elementos, por lo que el mapa produce una matriz de tres elementos.

6

De MDN:

de devolución de llamada se invoca sólo para los índices de la matriz que se han asignado valores; no se invoca para los índices que se han eliminado o que nunca tienen valores asignados.

Para la matriz a, ha instanciado una matriz de longitud 3 pero no ha asignado ningún valor. La función de mapa no encuentra elementos con valores asignados, por lo que no produce una nueva matriz.

Para la matriz b, ha instanciado una matriz de 3 elementos, cada uno con el valor undefined. La función de mapa encuentra 3 elementos con valores asignados, y devuelve '0' como el nuevo valor para cada uno de ellos en una nueva matriz.

3

map solo itera las propiedades existentes, no los índices vacíos.

Por lo tanto, si desea que funcione, primero debe llenar la matriz.

Hay múltiples maneras de hacerlo, por ejemplo:

  • .fill(), introducidos en ES6

    console.log(new Array(3).fill().map(function(){ return 0; }));

  • llamada concat con apply:

    var arr = [].concat.apply([], new Array(3)); 
     
    console.log(arr.map(function(){ return 0; }));

  • Un viejo for bucle.

    var arr = new Array(3); 
     
    for(var i=0; i<arr.length; ++i) arr[i] = 1; /* whatever */ 
     
    console.log(arr.map(function(){ return 0; }));

  • Uso alguna idea de Most efficient way to create a zero filled JavaScript array?

  • Etcétera.

Cuestiones relacionadas