2014-07-02 8 views
5

Próbuję nauczyć się JavaScript z książki Rhino. Próbowałem wykonać następujący kod z książki w odniesieniu do eval(). Korzystam z node.js (v0.10.29), aby wykonać przykłady.Node.js Global eval, rzucając 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' 

jednak otrzymuję ReferenceError wewnątrz funkcji g() gdy nie jest próbą użyć 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) 

Z tego co rozumiem, kiedy alias eval() jako geval(), kod w Łańcuch przekazany jest oceniany w globalnym zakresie według ES5. Jednak korzystam z wersji ReferenceError i nie rozumiem, dlaczego tak się dzieje.

Chociaż nie uważam, że eval() ma być funkcją krytyczną, zdecydowanie chciałbym zrozumieć, dlaczego napotykam takie zachowanie.

P.S. Kiedy próbuję wykonać ten sam kod w Google Chrome, wydaje się działać jak urok! Dziwne!

Odpowiedz

4

Problem jest, że używasz tego kodu z modułu, w którym var y = global; faktycznie definiuje y w modułu zakres, a nie globalny zakres.

W przeglądarkach zasięg najwyższego poziomu to zasięg globalny. Oznacza to, że w przeglądarkach, jeśli masz zasięg globalny, coś zdefiniuje globalną zmienną . W Węzłach jest inaczej. Zakres najwyższego poziomu nie jest zasięgiem globalnym; var coś wewnątrz modułu węzła będzie lokalne dla tego modułu.

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

więc dwa możliwe sposoby, aby to działało w węźle są:

  1. uruchomić go jak jest w węźle REPL
  2. uruchomić go w module, ale zastąpić var y = global; z tylko y = global;
+0

Dlaczego więc "console.log (f(), x);" działa? – thefourtheye

+2

Ponieważ w takim przypadku 'eval' jest wywoływany * bezpośrednio *, więc jest wykonywany w tym samym zakresie co' var x = 'local'; 'jest zdefiniowany w. (Patrz http://perfectionkills.com/global-eval- jakie są opcje/dla rozróżnienia między wywołaniem "eval" bezpośrednio i pośrednio.) – Emmett

+2

Dzięki, że odpowiada na pytanie. Tak więc 'var y = 'global';' faktycznie tworzy zmienną o zakresie modułów, a więc 'geval ('y + =" changed ";')' faktycznie nie może znaleźć 'y' w zasięgu globalnym. – codematix