Javascript - Evita la ridondanza variabile nei loop nidificati

3

Soddisfatti, potrei solo spiegare il problema nei commenti del frammento di codice qui sotto. Per favore leggili attentamente. Domanda alla fine:

Solitamente tendo a nominare le variabili utilizzate in for loops con i , in questo modo:

 for (var i = 0; i < arr.length; i++){
      // do some COMPLEX operations here
 }

Questo sembra abbastanza semplice; ma quando ci sono, posso richiedere cicli nidificati all'interno del ciclo for sopra. Quindi, introducendo la complessità ora:

 for (var i = 0; i < arr.length; i++) {
      // do some
      // VERY
      // COMPLEX
      // operations
      // here

      for (var i = 0; i < javascript_object.list.length; i++) {
          // I may have inadvertently forgot of the variable 'i' was been used earlier
          for (var j = 0; j < javascript_object.list[i].another_list.length; j++) {
              // Perform more complex operations here
          }
      }

      this.getReports(arr[i]) // the value of this i
         // which I now think refer to the first for loop might have been changed
         // in second for loop and may lead to dangerous results! 
 }

Come evitare che ciò accada? In che modo le variabili possono essere nominate con attenzione in modo da non scontrarsi con altre variabili dichiarate altrove?

    
posta Vineeth 23.09.2013 - 14:28
fonte

5 risposte

10

Un approccio comune, che è anche usato nel codice che hai postato è semplicemente per usare la prossima lettera dell'alfabeto, quindi:

for(var i = 0; i < length; i++) {
    for(var j = 0; j < length; j++) {
        for(var k = 0; k < length; k++) {
            // More loops?
        }
    }
}

Questo approccio è pigro, ma funziona. Tuttavia, trovo che possa creare confusione quando non si esegue il loop della stessa matrice o si accede a una matrice multidimensionale. In tal caso, un approccio migliore potrebbe essere semplicemente fornire nomi più significativi:

for(var nameIndex = 0; nameIndex < names.length; nameIndex++) {
    for(var classroomIndex = 0; classroomIndex < classrooms.length; classroomIndex++) {
        // And so forth
    }
}

Naturalmente questo potrebbe essere un po 'prolisso per te, ma immagino meglio un po' prolisso di codice completamente incomprensibile. Probabilmente stavate sperando in un preciso trucco per mantenere la variabile i nel proprio ambito. Potrebbe persino esistere un modo per farlo, tuttavia non credo in questo tipo di soluzione a un problema come questo per due motivi:

  • I loop annidati dovrebbero generalmente essere scoraggiati comunque. Non puoi applicare una buona pratica in una situazione in cui non stai seguendo una buona pratica. Chiama invece un metodo.
  • Avrebbe lasciato il programmatore successivo grattarsi la testa chiedendosi perché l'avessi fatto in quel modo, ed è difficile giustificare tale diminuzione della leggibilità solo per spiegare il conflitto di nomi.

Spero che ti aiuti!

    
risposta data 23.09.2013 - 14:39
fonte
14

Semplice:

  // This block with a
  // VERY
  // COMPLEX
  // operation
  // here
  // is far too large.

Quando i blocchi diventano così grandi da non poter più vedere tutte le definizioni delle variabili locali, sono decisamente troppo grandi. Rifinire tali parti in una funzione, questo aiuterà molto ad evitare doppie dichiarazioni accidentalmente.

    
risposta data 23.09.2013 - 14:39
fonte
1

Nel tuo esempio il valore di i utilizzerà sicuramente quello che si trova nel secondo ciclo. Questo perché le variabili sono scope della funzione in JavaScript. Quindi non importa quante volte tu var in una funzione, sarà la stessa variabile.

Per evitare ciò, dare le variabili ai nuovi nomi o racchiuderli in altre chiamate di funzione. Dato che non hai specificato cosa siano queste operazioni "complesse", non posso suggerire alcun buon metodo di refactoring oltre a estrarre il secondo per il ciclo nella sua funzione.

    
risposta data 23.09.2013 - 14:52
fonte
1

Usa JSLint o JSHint per filtrare il codice direttamente all'interno del tuo IDE / Editor. Dal libro "JavaScript: le parti buone" di Douglas Crockford (autore di JSLint ):

JSLint is a code quality tool for JavaScript. It takes a source text and scans it. If it finds a problem, it returns a message describing the problem and an approximate location within the source. The problem is not necessarily a syntax error, although it often is. JSLint looks at some style conventions as well as structural problems. It does not prove that your program is correct. It just provides another set of eyes to help spot problems.

    
risposta data 14.01.2014 - 11:43
fonte
1

Se hai usato un transpiler e hai usato la parola chiave "let" invece di "var", avresti ricevuto un errore nella seconda dichiarazione.

for (let i = 0; i < condition1; ++i) {

    // SyntaxError: Identifier 'i' has already been declared
    for (let i = 0; i < condition2; ++i) {  
    }
}

ma come altri hanno sottolineato, link , una lunghezza di funzione superiore a 8-10 linee è probabilmente troppo lunga.

    
risposta data 11.03.2018 - 14:49
fonte

Leggi altre domande sui tag