这是 Chrome 错误还是我使用“use strict”和 eval 无效?
Posted
技术标签:
【中文标题】这是 Chrome 错误还是我使用“use strict”和 eval 无效?【英文标题】:Is this a Chrome bug or is my use of "use strict" and eval invalid? 【发布时间】:2014-10-15 00:17:55 【问题描述】:此代码在除 Chrome 之外的所有浏览器中都可以正常工作:
eval("var outer = 0; function test() 'use strict'; outer = 1; test(); alert('ok');");
(试试 jsfiddle)。
我所做的只是从'use strict'
函数中引用一个外部变量,所有这些都在eval
上下文中。铬说
Uncaught ReferenceError: outer is not defined
注意:我最初在使用devtool: 'eval'
in Webpack时遇到了它。
【问题讨论】:
您的小提琴设置为使用 jsFiddle 的非常令人惊讶的默认,将您的所有代码包装在window.onload
处理程序中。 (左侧的第二个下拉菜单。)如果您将其关闭,代码(在全局范围内)将按预期工作:jsfiddle.net/rokkkjcs/2 我也在不使用 jsFiddle 的情况下验证了这一点(以防 jsFiddle 做一些奇怪的事情) .所以这就引出了一个问题:为什么 eval 是在函数内发生还是在全局范围内发生重要?无论哪种方式,test
应该关闭 outer
... V. v. 怪异的。
哦,我有没有提到当你直接从控制台的 REPL 运行它时它可以工作(即使包装在一个函数中)?越来越好奇......
使用 eval 在政治上是不正确的。
@frenchie 你知道我为什么要使用它吗?
【参考方案1】:
为了简化问题:http://jsfiddle.net/rokkkjcs/6/
eval("var outer=0;");
function test() 'use strict'; outer = 1;
test();
alert('ok');
而解释是:
非严格代码可以使用“eval”函数将新变量添加到周围范围。在浏览器支持原生 JSON 之前,“eval”通常(且不安全)用于从字符串构造对象。然后,构建的对象成为周围范围的一部分。在严格模式下,“eval”不能引入新变量。在严格模式下执行时,以下代码不会将“bar”变量引入周围范围。注意:如果包含‘eval’的函数在严格模式下执行,那么‘eval’函数内的代码也会在严格模式下执行。
更多信息:http://cjihrig.com/blog/javascripts-strict-mode-and-why-you-should-use-it/
【讨论】:
我不太确定我理解你的意思。您是否声称您的示例与我的示例相同?你能解释一下为什么吗? 唯一的问题是使用eval()
向周围范围添加一个新变量。在严格模式下,该变量将不可用。它可以在没有包装的情况下工作,因为它在全局范围内。
但是 eval 不是在严格模式下执行的,是吗?【参考方案2】:
实际上 eval 在定义它的范围内创建变量或修改变量,无论您是否使用 val。或者换句话说,默认情况下它没有自己的范围。
所以当你这样做时
eval("var outer = 0;");
console.log(outer); //0
您在外部范围内创建变量。令人惊讶的是,这在 chrome 中也以相同的方式工作 - 是否使用 window.onload 并不重要。
要使 eval 有它自己的范围,你必须执行以下操作:
eval("'use strict'; var outer = 0;");
console.log(outer); //Uncaught ReferenceError: outer is not defined
现在有一个单独的 eval 范围。 在 eval 中使用“use strict”,您的代码将在 chrome 中运行,并且不允许覆盖 eval 之外的变量。
eval("'use strict'; var outer = 0; function test() 'use strict'; outer = 1; test(); alert('ok');");
所以这部分回答了如何避免错误。
第二部分我很感兴趣,但自己找不到答案。
问题如下,为什么你的代码在 chrome 中抛出错误,而这在 chrome 中有效(这意味着创建了全局变量):
window.onload = function()
eval("var outer = 0; function test()console.log(outer); test();");
还有为什么它只发生在window.onload
。
【讨论】:
以上是关于这是 Chrome 错误还是我使用“use strict”和 eval 无效?的主要内容,如果未能解决你的问题,请参考以下文章