`var myEval = eval; 有什么问题?我的评估(“2+2”)`

What's wrong with `var myEval = eval; myEval("2+2")`

根据MDN-EVAL

You cannot indirectly use the eval function by invoking it via a name other than eval(); if you do, a runtime error might occur. For example, you should not use the following code:

var x = 2; //1
var y = 4; //2
var myEval = eval; //3
eval("x + y"); //4
myEval("x + y"); //5

正常情况 JavaScript 不会考虑 var someReference = someFunctionReference; 但是 eval 是特例,所以我可以期待一些惊喜。

现在让我们在非严格模式下看看下面的一些运行s

  1. Firefox/Aurora(V39.0)不介意和上面的代码运行没关系。
  2. Chrome(V 42.0.2311.135 m) 与 V8 4.2.77.18 运行s 很好。 (V8 版本取自 chrome://version/)
  3. 带有 V8 3.14.5.9 的节点(V0.10.35)抱怨错误 x 在第 5 行未定义 (取自 node -e "console.log(process.versions.v8)" 的 V8 版本)

现在我的问题是为什么会有不同的行为,how/when采用这种编码风格会给我的程序带来风险。

P.S.: //4 行没有抱怨任何 运行 中的任何错误而且我在上面的 运行 中假设 chrome/firefox 控制台 运行 在非严格模式下。

eval很特别。从 ES5 (~2009) 开始,对 eval 的直接调用在当前范围内有效,但对它的 间接 调用与你的 myEval 在全局范围内有效范围。这在 §10.4.2 and §15.1.2.1.1.

中有详细说明

因此,如果您的代码 运行 在一个函数中,例如:

function foo() {
    var x = 2;
    var y = 4;
    var myEval = eval;
    myEval("x + y");
}

...然后 正确 ES5 的行为将抱怨 x 不存在。

如果您的代码在所有函数之外的全局范围内,例如:

var x = 2;
var y = 4;
var myEval = eval;
myEval("x + y");

...那么正确的行为是得到结果 6。完整示例如下。

Now my query is why are there different behavior...

如果您 运行 在浏览器 控制台 中使用该代码,则可能取决于控制台实现(例如,一个控制台可能会在一个控制台中评估您的代码函数,另一个全局函数)。 console是一个特殊的环境,像这样的scope相关的东西最好用普通的页面测试。

and how/when doing this coding style brings risk to my program.

直接或间接使用 eval 风险 没有显着差异。风险来自对您无法控制的输入使用 eval(完全)。如果您从用户那里获取输入并 运行 立即将其安装到他们的计算机上,则风险主要由他们承担。但是,如果您从一个用户那里获取输入,然后稍后 运行通过 eval 另一个 用户的计算机或您的服务器上进行输入,这是一个很大的风险: 您允许该用户联系并 运行 在不属于他们的机器上编写代码。

P.S.: My assumption in the above runs that chrome/firefox console run in non-strict mode.

严格模式不会影响 eval 的这一方面。 (它确实影响它的其他方面,特别是它是否可以在局部范围内创建变量[它可以在松散模式下,它不能在严格模式下];这也在§ 10.4.2.)


实例:

function direct() {
  var x = 2;
  var y = 4;
  return eval("x + y");
}

function indirect() {
  var x = 2;
  var y = 4;
  var myEval = eval;
  return myEval("x + y");
}

snippet.log("Direct (within function):");
try {
  snippet.log("Got " + direct());
}
catch (e) {
  snippet.log("Got exception: " + e.message);
}

snippet.log("Indirect (within function):");
try {
  snippet.log("Got " + indirect());
}
catch (e) {
  snippet.log("Got exception: " + e.message);
}

var globalX = 2;
var globalY = 4;

snippet.log("Direct (at global scope):");
try {
  snippet.log("Got " + eval("globalX + globalY"));
}
catch (e) {
  snippet.log("Got exception: " + e.message);
}

snippet.log("Indirect (at global scope):");
var myGlobalEval = eval;
try {
  snippet.log("Got " + myGlobalEval("globalX + globalY"));
}
catch (e) {
  snippet.log("Got exception: " + e.message);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

正确的行为是显示:

Direct (within function):
Got 6
Indirect (within function):
Got exception: x is not defined
Direct (at global scope):
Got 6
Indirect (at global scope):
Got 6