2009-06-06 3 views
23

O più specifico di quello che mi serve:Le variabili sono "scopate" staticamente o dinamicamente in javascript?

Se chiamo una funzione da un'altra funzione, estrarrà la variabile dalla funzione di chiamata o dal livello superiore? Es:

myVar=0; 

function runMe(){ 
    myVar = 10; 
    callMe(); 
} 

function callMe(){ 
    addMe = myVar+10; 
} 

Cosa succede a myVar se callMe() viene chiamato tramite runMe()?

+11

Perché non lo esegui e lo scopri? –

+0

Non è meglio documentare la domanda in modo che anche gli altri possano vederla? – affinehat

risposta

39

Jeff ha ragione. Si noti che questo non è in realtà un buon test di scoping statico (che JS ha). Uno migliore sarebbe:

myVar=0; 

function runMe(){ 
    var myVar = 10; 
    callMe(); 
} 

function callMe(){ 
    addMe = myVar+10; 
} 

runMe(); 
alert(addMe); 
alert(myVar); 

In un linguaggio ambito statico (come JS), che avvisa il 10 e 0. Il myVar var (variabile locale) nel RunMe ombre myVar globale in quella funzione. Tuttavia, non ha alcun effetto in callme, così callme utilizza il myVar globale che è ancora a 0.

In un linguaggio ambito in modo dinamico (a differenza JS), callme avrebbe ereditato portata da RunMe, così AddMe diventerebbe 20. Notare che myVar sarebbe ancora 0 all'avviso, poiché l'avviso non eredita l'ambito da nessuna delle due funzioni.

+9

l'eccezione è la parola chiave 'this' che si comporta come una variabile con ambito dinamico – Jaksa

3

se la riga successiva è callMe();, quindi addMe sarà 10 e myVar sarà 0.

se la riga successiva è runMe();, quindi addMe sarà 20 e myVar sarà 10.

Perdonami per aver chiesto - che cosa ha a che fare con il binding statico/dinamico? Non è myVar semplicemente una variabile globale, e il codice procedurale (unwrap tutto nello stack di chiamate) non determinerà i valori?

+0

intendevo scope ... – kylex

2

Le variabili hanno uno scope statico in JavaScript (lo scope dinamico è davvero un business piuttosto disordinato: puoi leggere ulteriori informazioni a riguardo su Wikipedia).

Nel tuo caso, però, stai utilizzando una variabile globale, quindi tutte le funzioni accederanno alla stessa variabile. La risposta di Matthew Flaschen mostra come è possibile modificarla in modo che la seconda myVar sia in realtà una variabile diversa.

This Page spiega come dichiarare variabili globali e locali in JavaScript, nel caso in cui non si abbia familiarità con esso. È diverso dal modo in cui la maggior parte dei linguaggi di scripting lo fa. (In sintesi: la parola chiave "var" fa una variabile locale, se dichiarata all'interno di una funzione, altrimenti la variabile è globale.)

0

Per quanto ho capito, qualsiasi variabile senza la var parola chiave è trattato globale, con essa, i suoi locali con scope, quindi:

// This is a local scoped variable. 
var local_var = "something"; 

// This is a global scoped variable. 
global_var = "something_else"; 

Come una buona pratica JS, si consiglia di aggiungere sempre la var parola chiave.

1

A meno che non si utilizzi la parola chiave var per definire le variabili, tutto diventa una proprietà sull'oggetto window.Quindi il tuo codice sarebbe equivalente al seguente:

window.myVar=0; 

function runMe(){ 
    window.myVar = 10; 
    window.callMe(); 
} 

function callMe(){ 
    window.addMe = window.myVar+10; 
} 

Se tieni questo a mente, dovrebbe essere sempre chiaro cosa sta succedendo.

0

Vorrei aggiungere che le espressioni lambda sono anche con scope statico nella posizione in cui è definita l'espressione. Ad esempio,

var myVar = 0; 

function foo() { 
    var myVar = 10; 
    return { bar: function() { addMe = myVar + 10; }} 
} 

var myObj = foo(); 

var addMe = 6; 
alert(addMe); 

myVar = 42; 
myObj.bar(); 

alert(addMe); 

Questo visualizzerà 6 e 20.

0
myVar=0; 

function runMe(){ 
    myVar = 10; 
    callMe(); 
} 

function callMe(){ 
    addMe = myVar+10; 
} 

Per quanto riguarda l'uscita concerne myVar e ADDME entrambi sarà variabile globale in questo caso, come in JavaScript se si don' t dichiarare una variabile con var quindi lo dichiara implicitamente come globale, quindi quando si chiama runMe() allora myVar avrà il valore 10 e addMe avrà 20.