`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
- Firefox/Aurora(V39.0)不介意和上面的代码运行没关系。
- Chrome(V 42.0.2311.135 m) 与 V8 4.2.77.18 运行s 很好。 (V8 版本取自 chrome://version/)
- 带有 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
根据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
- Firefox/Aurora(V39.0)不介意和上面的代码运行没关系。
- Chrome(V 42.0.2311.135 m) 与 V8 4.2.77.18 运行s 很好。 (V8 版本取自 chrome://version/)
- 带有 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