Domanda Passa attraverso un array in JavaScript


In Java puoi usare a for loop per attraversare oggetti in un array come segue:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

Puoi fare lo stesso in JavaScript?


2415
2018-06-10 00:04


origine


risposte:


Usa un sequenziale for ciclo continuo:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    alert(myStringArray[i]);
    //Do something
}

@zipcodeman suggerisce l'uso di for...in affermazione, ma per iterare gli array for-in dovrebbe essere evitato, questa affermazione è destinata a enumerare proprietà dell'oggetto.

Non dovrebbe essere usato per oggetti di tipo array perché:

  • L'ordine di iterazione non è garantito, gli indici di array non possono essere visitati in ordine numerico.
  • Anche le proprietà ereditate sono elencate.

Il secondo punto è che può darti molti problemi, ad esempio, se estendi il Array.prototype oggetto di includere un metodo lì, quella proprietà sarà anche enumerata.

Per esempio:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
  alert(array[i]);
}

Il codice sopra avviserà "a", "b", "c" e "foo!".

Questo è particolarmente un problema se si utilizza una libreria che si basa molto sul potenziamento dei prototipi nativi (come ad esempio MooTools).

Il for-in dichiarazione come ho detto prima è lì per enumerare proprietà dell'oggetto, ad esempio:

var obj = {
  "a": 1,
  "b": 2,
  "c": 3
};

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) { 
  // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
    alert("prop: " + prop + " value: " + obj[prop])
  }
}

Nell'esempio sopra il hasOwnProperty metodo consente di enumerare solo proprie proprietà, questo è tutto, solo le proprietà che l'oggetto ha fisicamente, nessuna proprietà ereditata.

Ti consiglierei di leggere il seguente articolo:


3048
2018-06-10 00:07



Sì, ma solo se la tua implementazione include il for...of funzionalità introdotta in ECMAScript 2015 (la versione "Harmony").

Funziona così:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

O meglio ancora, dal momento che ECMAScript 2015 fornisce anche variabili con scope a blocchi tramite let e const:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

Molti sviluppatori JavaScript stanno ancora lavorando in un ambiente che non c'è ancora, tuttavia, specialmente se si scrive codice per essere eseguito nei browser web, dove gli sviluppatori del sito spesso non sono sicuri di quale browser / versione useranno i propri client.

Se si può supporre che l'interprete JavaScript sia compatibile con precedente edizione della specifica ECMAScript (che esclude, ad esempio, le versioni di Internet Explorer prima delle 9), quindi è possibile utilizzare il forEach metodo iteratore invece di un ciclo. In tal caso, si passa una funzione da chiamare su ciascun elemento dell'array:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

Ma se anche quello è troppo da assumere, e vuoi qualcosa in cui funzioni tutti versioni di JavaScript, quindi è necessario utilizzare un ciclo di conteggio esplicito. La versione più sicura, che gestisce correttamente gli array sparsi, è qualcosa del genere:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Assegnare il valore della lunghezza alla variabile locale (anziché includere il pieno myStringArray.length espressione nella condizione del ciclo) può fare una differenza significativa nelle prestazioni poiché ignora ogni volta una ricerca di proprietà; usando Rhino sulla mia macchina, la velocità è del 43%.

Vedrai spesso la cache di lunghezza eseguita nella clausola di inizializzazione del ciclo, come questa:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

Il for...in la sintassi menzionata da altri è per il looping sulle proprietà di un oggetto; poiché una matrice in JavaScript è solo un oggetto con nomi di proprietà numeriche (e un aggiornamento automatico lengthproprietà), è teoricamente possibile eseguire il loop su una matrice con esso. Ma il problema è che non si limita ai valori delle proprietà numeriche (ricorda che anche i metodi sono in realtà solo proprietà il cui valore è una chiusura), né itera su quelli in ordine numerico. quindi, il for...in la sintassi dovrebbe non essere utilizzato per il loop attraverso gli array.


867
2018-04-16 02:03



Puoi usare map, che è una tecnica di programmazione funzionale che è disponibile anche in altre lingue come Pitone e Haskell.

[1,2,3,4].map( function(item) {
     alert(item);
})

La sintassi generale è:

array.map(func)

In generale func prenderebbe un parametro, che è un elemento dell'array. Ma nel caso di JavaScript, può prendere un secondo parametro che è l'indice dell'oggetto e un terzo parametro che è l'array stesso.

Il valore di ritorno di array.map è un altro array, quindi puoi usarlo in questo modo:

var x = [1,2,3,4].map( function(item) {return item * 10;});

E ora x è [10,20,30,40].

Non è necessario scrivere la funzione in linea. Potrebbe essere una funzione separata.

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

che sarebbe in qualche modo equivalente a:

 for (item in my_list) {item_processor(item);}

Tranne che non ottieni il new_list.


391
2018-06-10 00:09



In JavaScript non è consigliabile eseguire il ciclo di una matrice con un ciclo for-in, ma è meglio utilizzare un ciclo for come:

for(var i=0, len=myArray.length; i < len; i++){}

È anche ottimizzato ("memorizzazione nella cache" della lunghezza dell'array). Se desideri saperne di più, leggi il mio post sull'argomento.


102
2017-12-07 07:24



for (var s of myStringArray) {

(Rispondendo direttamente alla tua domanda: ora puoi!)

La maggior parte delle altre risposte ha ragione, ma non menzionano (come da questo scritto) quello Script ECMA 6 2015 sta portando un nuovo meccanismo per fare l'iterazione, il for..of ciclo continuo.

Questa nuova sintassi è il modo più elegante per iterare un array in javascript (a patto che non sia necessario l'indice di iterazione), ma non è ancora ampiamente supportato dai browser.

Attualmente funziona con Firefox 13+, Chrome 37+ e non funziona in modo nativo con altri browser (vedi la compatibilità del browser sotto). Fortunatamente abbiamo compilatori JS (come ad esempio Babele) che ci consentono di utilizzare le funzionalità di prossima generazione oggi.

Funziona anche su Node (l'ho testato sulla versione 0.12.0).

Iterazione di un array

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

Iterazione di una matrice di oggetti

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var member of band){
  console.log(member.firstName + ' ' + member.lastName); 
}

Iterazione di un generatore:

(esempio estratto da https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)

function* fibonacci() { // a generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Tabella di compatibilità: http://kangax.github.io/es5-compat-table/es6/#For..of loops

Spec:  http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}


92
2017-08-11 15:54



Opera, Safari, Firefox e Chrome condividono ora una serie di metodi Array avanzati per l'ottimizzazione di molti loop comuni.

Potresti non averne bisogno tutti, ma possono essere molto utili, o lo sarebbero se tutti i browser li supportassero.

Mozilla Labs ha pubblicato gli algoritmi che essi e WebKit entrambi usano, in modo che tu possa aggiungerli tu stesso.

filtro restituisce una serie di elementi che soddisfano alcune condizioni o test.

ogni restituisce true se ogni membro dell'array supera il test.

alcuni restituisce true se qualcuno supera il test.

per ciascuno esegue una funzione su ogni membro dell'array e non restituisce nulla.

carta geografica è come forEach, ma restituisce una matrice dei risultati dell'operazione per ciascun elemento.

Questi metodi hanno tutti una funzione per il loro primo argomento e hanno un secondo argomento opzionale, che è un oggetto il cui ambito si desidera imporre ai membri dell'array mentre passano attraverso la funzione.

Ignoralo finché non ne hai bisogno.

indice di e lastIndexOf trova la posizione appropriata del primo o dell'ultimo elemento che corrisponde esattamente al suo argomento.

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();

81
2018-06-10 02:43



Usa il ciclo while ...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

registri: 'uno', 'due', 'tre'

E per l'ordine inverso, un ciclo ancora più efficiente

var items = ['one','two','three'], i = items.length;
while(i--){
    console.log(items[i]);
}

registri: 'tre', 'due', 'uno'

O il classico for ciclo continuo

var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

registri: 'uno', 'due', 'tre'

Riferimento: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


62
2018-01-05 09:15