2014-05-04 12 views
11

Mi chiedo solo perché non sia possibile creare un numero di array indefinito.forEach su array di undefined creato dal costruttore di array

Codice:

var arr = new Array(5); // [undefined x 5] 

//ES5 forEach 
arr.forEach(function(elem, index, array) { 
    console.log(index); 
}); 

//underscore each 
_.each(arr, function(elem, index, array) { 
    console.log(index); 
}); 

Entrambi gli esempi non eseguire la funzione.

ora a fare foreach, devo fare:

var arr = [0,0,0,0,0]; 

poi fare forEach su di esso.

Sto provando a creare un array con le dimensioni specificate e ad attraversarlo, evitando il ciclo for. Penso che sia più chiaro usando forEach che for loop. Con array con lunghezza 5 non è un problema, ma sarebbe brutto con array più grandi.

Perché esiste un problema durante il looping di un array di valori non definiti?

+3

Perché 'Array (5)' non è una matrice di 'indefinito'. Ha esattamente membri '0' anche se il suo' .length' è stato predefinito. –

+1

... anche se non sono sicuro di cosa ti aspetti quando dici gli esempi "return' undefined' ". Il metodo '.forEach()' restituirà sempre 'undefined', indipendentemente da cosa itera sopra. Sembra che la domanda dovrebbe essere se il callback è stato richiamato o meno. –

+0

Hai ragione, non restituire undefined, ma non eseguire la funzione. – Tukkan

risposta

19

Array(5) è essentialy equivalente a

var arr = []; 
arr.length = 5; 

in JavaScript cambiando la lunghezza dell'array non impostare i valori per le sue proprietà numeriche né definisce tali proprietà nell'oggetto matrice. Quindi le proprietà numeriche non sono definite invece di avere un valore non definito. È possibile controllare esso utilizzando:

Object.keys(arr) 

Quando l'iterazione itera JavaScript attraverso le proprietà numeriche dell'array, quindi se queste non esistono, non c'è nulla da iterare.

È possibile controllare da fare:

var arr = Array(5) 

//prints nothing 
arr.forEach(function(elem, index, array) { 
    console.log(index); 
}); 

arr[3] = 'hey' 
//prints only 'hey' even though arr.length === 5 
arr.forEach(function(elem, index, array) { 
    console.log(index); 
}); 

Il seguente codice:

var arr = [undefined, undefined]; 

crea e la matrice di length ===2 e imposta le proprietà sia numerici 0 e 1 per indefinita.

+0

puoi spiegare anche il comportamento dell'operatore di spread in questo caso? – Hitmands

3

Può essere utile una implementazione semplificata di .forEach().

Array.prototype.my_for_each = function(callback, thisArg) { 
    for (var i = 0; i < this.length; i++) { 
     if (i in this) { 
      callback.call(thisArg, this[i], i, this); 
     } 
    } 
}; 

Così si può vedere che ciò che accade è che il metodo fa iterare l'intero array (secondo le specifiche), ma richiama solo il callback se il membro esiste realmente. Controlla la proprietà (l'indice) utilizzando l'operatore in, che verifica se l'oggetto ha o eredita la proprietà.

Se in indica che l'indice esiste, viene richiamato il callback.


Quindi, dato queste Array:

var arr = ["foo", "bar", "baz"]; 

Questo emette tutti i 3 articoli:

arr.my_for_each(function(item) { 
    console.log(item); 
}); 
// "foo" "bar" "baz" 

Ma se usiamo delete di rimuovere un membro, che lascia un buco nel Array , che ora verrà passato sopra.

delete arr[1]; 

arr.my_for_each(function(item) { 
    console.log(item); 
}); 
// "foo" "baz" 

Quando si è creato un array usando Array(5), ha creato uno senza alcun membro, ma con la .length set per 5. Quindi questo è un esempio di una matrice sparsa (molto sparsa in questo caso). Poiché nessuno degli indici sarà trovato da in, la richiamata non viene mai richiamata.