2012-05-04 13 views
10

Ho un oggetto con matrici come valori.JSHint non mi consente di utilizzare "forEach" in un ciclo "for"

people = { 
    'steve':['foo','bar'], 
    'joe':['baz','boo'] 
} 

Per ciascuna chiave, desidero ciclo sui valori nella matrice corrispondente. Abbastanza semplice:

for (var person in people) { 
    person.forEach(function(item) { 
     console.log(item) 
    }) 
} 

Ma JSHint lamenta:

Don't make functions within a loop. 

È questo davvero un problema con il mio codice? Mi piace molto il corto ES5 per la sintassi del loop. Devo usare lo stile ES3 o cambiare il mio codice in qualche altro modo?

risposta

18

Ci sono due problemi, quello di cui JSHint ti avvisa e uno più fondamentale.

La cosa di cui JSHint ti avvisa è che in teoria, ogni volta che viene eseguito il ciclo, viene creata una nuova funzione. Questo sarebbe meglio:

for (var person in people) { 
    person.forEach(handlePerson); 
} 
function handlePerson(item) { 
    console.log(item) 
} 

dico "in teoria" perché anche se le specifiche richiede che un nuovo oggetto funzione creato ogni volta, ciò non significa motori non può riutilizzare il sottostante attuazione della funzione, e ciò non significa che i motori non possano riutilizzare lo stesso oggetto funzione se non gli hai assegnato altre proprietà o tieni un riferimento ad esso. I asked the V8 guys about it (V8 è il motore JavaScript in Chrome) e hanno detto che Chrome "... nella maggior parte dei casi ..." riutilizza l'implementazione della funzione sottostante per diversi oggetti funzione creati nello stesso punto nel codice sorgente e che si sarebbero "aspettati" che la maggior parte degli altri motori avrebbe fatto lo stesso.

Quindi JSHint potrebbe essere un po 'esagerato in questo caso particolare. Ma è spesso un avvertimento utile, in particolare se le funzioni che stai creando all'interno del ciclo si riferiscono a variabili il cui contenuto cambia durante il ciclo, che è il classico errore di chiusura che le persone fanno.

Ma più fondamentalmente, è un personString (è il nome di una proprietà in people), e String non avere forEach. Volevi:.

for (var person in people) { 
    people[person].forEach(handlePerson); 
} 
function handlePerson(item) { 
    console.log(item) 
} 

... per esempio, people[person] per ottenere la matrice per quella chiave.

+1

Immagino che intendesse "persone [persona] .for Ogni (...)". Ad ogni modo, questo avvertimento sembra essere piuttosto stupido con i moderni motori JS - molto probabilmente non creeranno una nuova funzione per ogni iterazione. – ThiefMaster

+0

Almeno V8 non: http://stackoverflow.com/questions/10160275/v8-internals-handling-of-anonymous-functions – ThiefMaster

+0

'persone' è un oggetto (contenente matrici). –

1

È possibile utilizzare forEach all'interno del ciclo, ma non è possibile dichiarare una funzione all'interno di un ciclo.

function looper (item) { 
    console.log(item) 
} 

for (var person in people) { 
    person.forEach(looper) 
} 

... altrimenti si sta ricreando la stessa funzione per ogni iterazione.

0

Non è il forEach, è la funzione anonima di cui si lamenta.

0

Il motivo per cui questo è un problema è che crea un nuovo riferimento all'oggetto della funzione anonima all'interno della chiamata foreach nell'heap ogni volta che si esegue questa operazione.Sarebbe meglio se assegnassi la funzione a una variabile esterna al ciclo for, in questo modo non stai consumando memoria inutilmente

7

Oltre agli altri commentatori, se sai cosa stai facendo, puoi disabilitare questo avvertimento opzione JSHint loopfunc con:

/*jshint loopfunc:true */ 

for (var person in people) { 
    person.forEach(function(item) { 
    console.log(item) 
    }) 
} 

È possibile impostare le opzioni JSHint globale (se si sta utilizzando il modulo NPM), file per file o per-funzione.

+0

Leggendo questo nel 2016: ho fatto davvero ** non ** sapere cosa stavo facendo. PS. Ciao Anton! – mikemaccana