Node.js全局评估,抛出ReferenceError

7

我正在尝试从Rhino书籍学习JavaScript。我正在尝试执行书中关于eval()的以下代码。我正在使用node.js(v0.10.29)来执行这些示例。

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'

然而,当尝试使用geval()别名时,在g()函数内部会出现ReferenceError错误:
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) 

据我所知,当我将eval()重命名为geval()时,传递的字符串中的代码根据ES5在全局范围内运行。然而,我遇到了ReferenceError,无法理解其中原因。
虽然我不认为eval()是一个关键的功能,但我肯定会想要理解我遇到这种行为的原因。
顺便说一下,当我尝试在Google Chrome中执行相同的代码时,它似乎能够完美运行!奇怪!
1个回答

6
问题在于您正在从一个模块中运行此代码,在其中var y = global;实际上定义了y模块范围内,而不是全局范围。

在浏览器中,顶级作用域是全局作用域。这意味着在浏览器中,如果您在全局作用域中,var something将定义一个全局变量。但在Node中情况不同。顶级作用域不是全局作用域;在Node模块中,var something将是该模块的局部变量。

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

那么,在Node中使其工作的两种可能方法是:

  1. 在Node REPL 中按原样运行。
  2. 在一个模块中运行,但将 var y = global; 替换为 y = global;

2
因为在这种情况下,eval直接调用,所以它是在定义var x ='local';的相同作用域中执行的。(有关直接调用和间接调用eval之间的区别,请参见http://perfectionkills.com/global-eval-what-are-the-options/。) - Emmett
2
谢谢您的回答。所以 var y = 'global'; 实际上创建了一个模块作用域变量,因此 geval('y += "changed";') 无法在全局范围内找到 y - codematix
@Emmett +1,谢谢 :-) - thefourtheye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接