2014-07-02 12 views
5

Sto cercando di imparare JavaScript dal libro di Rhino. Stavo cercando di eseguire il seguente codice dal libro per quanto riguarda eval(). Sto usando node.js (v0.10.29) per eseguire gli esempi.Node.js Global eval, throwing ReferenceError

var geval = eval;     // aliasing eval to geval 
var x = 'global';     // two global variables 
var y = 'global'; 

function f() { 
    var x = 'local';     // define a local variable 
    eval('x += "changed";');   // direct eval sets the local variable 
    return x; 
} 

function g() { 
    var y = 'local';     // define a local variable 
    geval('y += "changed";');  // indirect eval sets global variable 
    return y; 
} 

console.log(f(), x);    // => expected 'localchanged global' 
console.log(g(), y);    // => expected 'local globalchanged' 

Tuttavia, ottengo un ReferenceError all'interno della funzione g() quando c'è un tentativo di utilizzare il geval() alias:

undefined:1 
y += "changed"; 
^ 
ReferenceError: y is not defined 
    at eval (eval at g (/Users/codematix/Learning/learnjs/expressions.js:148:3), <anonymous>:1:1) 
    at eval (native) 
    at g (/Users/codematix/Learning/learnjs/expressions.js:148:3) 
    at Object.<anonymous> (/Users/codematix/Learning/learnjs/expressions.js:153:3) 
    at Module._compile (module.js:456:26) 
    at Object.Module._extensions..js (module.js:474:10) 
    at Module.load (module.js:356:32) 
    at Function.Module._load (module.js:312:12) 
    at Function.Module.runMain (module.js:497:10) 
    at startup (node.js:119:16) 

Da quello che ho capito, quando ho creare un alias con eval() come geval(), il codice in stringa passata viene valutata in ambito globale secondo ES5. Tuttavia, sto correndo nel ReferenceError e non riesco a capire perché.

Anche se non considererei la funzione eval() una funzione critica, mi piacerebbe sicuramente capire perché sto riscontrando questo comportamento.

P.S. Quando provo a eseguire lo stesso codice in Google Chrome, sembra che funzioni come un incantesimo! Strano!

risposta

4

Il problema è che si esegue questo codice da un modulo, in cui var y = global; definisce effettivamente y in modulo ambito, non ambito globale.

Nei browser, l'ambito principale è l'ambito globale. Ciò significa che nei browser se si è nello scope globale var qualcosa definirà una variabile globale . Nel nodo questo è diverso. L'ambito di primo livello non è l'ambito globale; var qualcosa all'interno di un modulo Node sarà locale a quel modulo.

http://nodejs.org/api/globals.html#globals_global

Così, due possibili modi per ottenere questo a lavorare in nodo sono:

  1. Esegui come è nel nodo REPL
  2. Run in un modulo, ma sostituire var y = global; con solo y = global;
+0

Quindi perché 'console.log (f(), x);' funziona? – thefourtheye

+2

Perché in questo caso, 'eval' è chiamato * direttamente *, quindi è eseguito nello stesso ambito in cui' var x = 'local'; 'è definito in. (Vedi http://perfectionkills.com/global-eval- what-are-the-options/per la distinzione tra chiamare 'eval' direttamente e indirettamente.) – Emmett

+2

Grazie che risponde alla domanda. Quindi un 'var y = 'global';' sta effettivamente creando una variabile con scope del modulo e quindi 'geval ('y + =" changed ";')' in realtà non riesce a trovare 'y' nello scope globale. – codematix