`var myEval = eval有什么问题; myEval( “2 + 2”)`

时间:2015-05-08 06:48:41

标签: javascript eval

根据MDN-EVAL

  

您不能通过eval()以外的名称调用eval函数来间接使用eval函数;如果这样做,可能会发生运行时错误。例如,您不应使用以下代码:

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是特殊情况,所以我可以期待一些惊喜。

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

  1. Firefox / Aurora(V39.0)并不介意,上面的代码运行良好。
  2. Chrome(V 42.0.2311.135 m),V8 4.2.77.18运行良好。 (V8版本取自chrome:// version /)
  3. 带有V8 3.14.5.9的节点(V0.10.35)抱怨错误{5}未定义在第5行(V8版本取自节点-e“console.log(process.versions.v8) “)
  4. 现在我的查询是为什么会有不同的行为以及这种编码方式在何时/何时会给我的程序带来风险。

    P.S。:x行不会在任何运行中抱怨任何错误。我在上面的运行中假设chrome / firefox控制台以非严格模式运行。

1 个答案:

答案 0 :(得分:1)

eval很特别。从ES5(~2009)开始,对eval的直接调用在当前作用域内有效,但间接调用它与myEval一样适用于全局作用域。详情请参阅§10.4.2§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。完整的例子如下。

  

现在我的查询是为什么有不同的行为...

如果您在浏览器控制台中运行该代码,则可能是控制台实现(例如,一个控制台可能会评估您在函数中的代码,另一个控制台在全局范围内)。控制台是一个特殊的环境,与此相关的范围相关的东西最好用普通页面进行测试。

  

以及如何/何时执行此编码风格会给我的程序带来风险。

直接或间接使用eval风险没有显着差异。风险来自于对您无法控制的输入使用eval(根本)。如果您正在从用户那里获取输入并立即在他们的计算机上运行,​​则风险主要在于他们。但是,如果您从一个用户那里获取输入,然后通过另一个用户的计算机或服务器上的eval运行,则存在重大风险:您允许该用户伸出并在不属于他们的机器上运行代码。

  

P.S。:我在上面的假设中运行chrome / firefox控制台以非严格模式运行。

严格模式不会影响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