2012-05-04 26 views
17

Dire che sto cercando di eseguire questo snippet di JavaScript. Supponiamo che le vars e i metodi non dichiarati siano dichiarati altrove, sopra, e che something e somethingElse valgano per boolean-true.Ambito JavaScript in un blocco try

try { 
    if(something) { 
     var magicVar = -1; 
    } 

    if(somethingElse) { 
     magicFunction(magicVar); 
    } 
} catch(e) { 
    doSomethingWithError(e); 
} 

La mia domanda è: qual è la portata magicVar ed è bene passare in magicFunction come ho fatto?

+1

Mi sembra come questo è solo una domanda circa la portata variabile, non portata variabile all'interno di un blocco try. –

risposta

17

Javascript ha funzione scopo.Ciò significa che magicvar esisterà dall'inizio della funzione dichiarata fino alla fine di tale funzione, anche se tale istruzione non viene mai eseguita. Questo è chiamato sollevamento variabile. La stessa cosa accade con le dichiarazioni di funzioni, che a loro volta sono chiamate con funzione di sollevamento.

Se la variabile è dichiarata nell'ambito globale, sarà visibile a tutto. Questo è parte del motivo per cui le variabili globali sono considerate malvagie in Javascript.

Il tuo esempio passerà undefined in magicFunction se something è falso, perché magicVar non è stato assegnato a nulla.

Sebbene si tratti di un Javascript valido dal punto di vista tecnico, è generalmente considerato di cattivo gusto e non passerà pedine di stile come jsLint. Estremamente Javascript poco intuitivo come questo verrà eseguito senza alcun errore

alert(a); //alerts "undefined" 
var a; 

POP QUIZ: Cosa il seguente codice?

(function() { 
    x = 2; 
    var x; 
    alert(x); 
})(); 
alert(x); 
+1

L'esempio che hai dato non è abbastanza buono perché era 'indefinito 'in ogni caso, perché' window.a' è 'indefinito' – gdoron

+0

@ gdoron Non sono sicuro di vedere cosa stai ricevendo. Se si prova a eseguire 'alert (a)' da solo, genererà un errore come 'a is 'undefined''. –

+0

Il fatto è che 'a'_can_ essere indefinito perché non definito in outerscope. Dai un'occhiata a questo [demo] (http://jsfiddle.net/gdoron/H8c4n/3/) Se rimuovi 'var x' ottieni sempre lo stesso risultato. – gdoron

1

Con var, le variabili esistono dall'inizio della funzione fino alla fine di esso, indipendentemente da dove vengono dichiarate o anche se l'istruzione viene effettivamente raggiunta. Tuttavia, saranno undefined finché non verrà assegnato un altro valore.

Quindi nel tuo caso, se something è falso ma somethingelse è vero, si chiama magicFunction con il suo primo argomento essendo undefined.

Il let parola chiave, creato in Javascript 1.9 e disponibili (a partire da oggi, 3 maggio ° 2012, e per quanto ne so) solo in Firefox, dichiara variabili con la semantica con ambito probabilmente stai abituati.

5
  • In javascript, solo le funzioni creano un nuovo contesto -closure.
  • Ogni definizione di una variabile è in realtà una dichiarazione della variabile nella parte superiore del suo ambito e un'assegnazione nel luogo in cui si trova la definizione.

var

  • funzione-scope
  • paranco all'inizio della sua funzione
  • redeclarations lo stesso nome nello stesso ambito sono gabbie

Tu consiglia di leggere MDN scope cheat sheet

causa hoisting Si può anche fare cose come questa:

function bar() { 
    var x = "outer"; 

    function foo() { 
     alert(x); // {undefined} Doesn't refer to the outerscope x 
     // Due the the var hoising next:   
     x = 'inner'; 
     var x; 
     alert(x); // inner 

    } 
    foo(); 
} 

bar();​ 

bar();​ 

Demo

Quindi la funzione foo viene convertito in qualcosa di simile:

function foo() { 
    var x; 
    alert(x); // {undefined} Doesn't refer to the outerscope x 
    // Due the the var hoising next:   
    x = 'inner'; 
    alert(x); // inner 
}​ 

La mia domanda è: qual è lo scopo di magicVar an è giusto passare in magicFunction come ho fatto?

Definire bene ..., Sì, il codice è valido, ma è meno leggibile poi se le dichiarazioni variabili sono state in alto, questo è tutto.

+0

Sono distrutto! Amo sia il tuo che Peter Olson. Avere un upvote :) – user5243421

+0

@DarrenGreen. **:) ** Non sentirti male. Scegli la migliore risposta che pensi di avere. (Non mi piace l'idea Stackoverflow che accetta risposte in alto {ho sentito _hoisting_? :)}, non ha senso che il ragazzo che probabilmente ha meno conoscenza sulla domanda decida quale risposta è la migliore .) Se è la risposta di Peter, mi piace, non sono in competizione con le risposte. – gdoron

+0

Il tuo link cheat è considerato contenuto obsoleto. Adoro le grandi barre di avviso su quella pagina - non te lo perderai! haha – jcollum

3

perché JavaScript "sollevamento" (google), il codice di dichiarazione delle variabili si traduce come:

function yourFunction() { 
    var magicVar; 
    try { 
     if(something) { 
      magicVar = -1; 
     } 

     if(somethingElse) { 
      magicFunction(magicVar); 
     } 
    } catch(e) { 
     doSomethingWithError(e); 
    } 

} //end of your function 

"sollevamento" muove tutte le dichiarazioni variabili alla parte superiore della funzione. Quindi magicVar è disponibile ovunque nella funzione, ma non è definito fino a quando non gli si assegna un valore.

La variabile ha lo scopo della funzione.

14

Un sacco di altre buone risposte su come JavaScript gestisce questo con var, ma ho pensato di affrontare la situazione let ...

Se una variabile è definita con let all'interno del blocco try, non sarà nell'ambito del blocco catch (o finally). Dovrebbe essere definito nel blocco di chiusura.

Ad esempio, nel seguente blocco di codice, l'output della console sarà "Outside":

let xyz = "Outside"; 

try { 
    let xyz = "Inside"; 

    throw new Error("Blah"); 
} catch (err) { 
    console.log(xyz); 
} 
Problemi correlati