Javascript 为什么eval不';您无权访问with语句下的作用域变量吗?
为什么不能在Javascript 为什么eval不';您无权访问with语句下的作用域变量吗?,javascript,eval,with-statement,Javascript,Eval,With Statement,为什么不能在with语句下使用eval访问作用域变量 例如: (function (obj) { with (obj) { console.log(a); // prints out obj.a eval("console.log(a)"); // ReferenceError: a is not defined } })({ a: "hello" }) 编辑:正如知识渊博的CMS指出的,这似乎是一个浏览器错误(使用WebKit控制台的浏览器) 如果有人想
with
语句下使用eval
访问作用域变量
例如:
(function (obj) {
with (obj) {
console.log(a); // prints out obj.a
eval("console.log(a)"); // ReferenceError: a is not defined
}
})({ a: "hello" })
编辑:正如知识渊博的CMS指出的,这似乎是一个浏览器错误(使用WebKit控制台的浏览器)
如果有人想知道我想说的是什么讨厌的东西,那就需要“邪恶”eval
和with
——我想看看我是否能在另一个上下文而不是它定义的上下文中执行一个函数(用作回调)。不,我可能(咳嗽)不会在任何地方用这个。。比什么都奇怪
(function (context,fn) {
with (context)
eval("("+fn+")()");
})({ a: "hello there" }, function () { console.log(a); })
Eval总是在全局范围内运行,不是吗
(function (obj) {
with (obj) {
alert(a); // prints out obj.a
eval("alert(a)"); // ReferenceError: a is not defined
}
})({ a: "hello from a with eval" })
function testfunc(a) { eval("alert(a)"); } testfunc("hello from a testfunc eval");
(function (a) { eval("alert(a)"); })("hello from a function constructor eval")
所有工作正常:FF/Chrome/Safari/IE
从各种控制台运行代码片段的问题是,控制台通常会与上下文发生冲突。(也就是说,Chrome控制台似乎没有在全局上下文中正确地包装东西,而Firebug控制台却这样做了)。这可能是一个bug,或者(更可能)它可能按预期工作。这是一个只能从WebKit控制台复制的bug,当从
函数表达式调用eval
时,绑定调用方上下文时会出现问题
当直接调用eval
时,您所期望的经过评估的代码应该共享变量环境:
(function (arg) {
return eval('arg');
})('foo');
// should return 'foo', throws a ReferenceError from the WebKit console
(function () {
eval('var localVar = "test"');
})();
typeof localVar; // should be 'undefined', returns 'string' on the Console
还有词汇环境:
(function (arg) {
return eval('arg');
})('foo');
// should return 'foo', throws a ReferenceError from the WebKit console
(function () {
eval('var localVar = "test"');
})();
typeof localVar; // should be 'undefined', returns 'string' on the Console
在上面的函数中,localVar
应该在调用方的词法环境中声明,而不是在全局上下文中声明
对于FunctionDeclaration
s,如果我们尝试以下操作,则行为完全正常:
function test1(arg) {
return eval('arg');
}
test1('foo'); // properly returns 'foo' on the WebKit console
及
我已经能够在Windows Vista SP2上运行的以下浏览器上重现该问题:
- 铬5.0.375.125
- Chrome 6.0.472.25开发版
- Safari 5.0.1
- WebKit夜间构建r64893
抛开eval和with不谈,新的Bowser包括ecma5 Function.prototype.bind方法,用于在某些选定对象的范围内调用函数
对于较旧的浏览器,您可以伪造它-
Function.prototype.bind= Function.prototype.bind || function bind(scope){
var method= this;
return function(){
method.apply(scope, arguments);
}
}
您在哪个浏览器中获得此行为?您是否在某个控制台上运行代码?@CMS:Chrome 5.0.375.125 beta使用内置开发人员控制台。编辑:我刚刚在Firefox(firebug)上试过,效果如预期。一定是你说的浏览器错误。@Daniel-如果有帮助的话,它在Chrome 6.0.472.22中可以正常工作any@Nick,@Daniel,问题只出现在控制台上我在Chrome 6.0.472.25上得到了相同的行为,我很确定这个问题与WebKit控制台有关,因为它在Safari 5.0.1和WebKit夜间构建中也是可复制的,所以它似乎也不限于with
语句。简单的情况是:(函数(a){eval(“console.log(a)”;})(“hello”)
也会失败。除非其他人愿意,否则我将提交该问题。不,直接调用eval
将使用调用上下文(调用方词法和变量环境),间接调用ECMAScript 5中的eval,例如:var foo=eval;foo(“代码”)
将使用全局上下文以及函数构造函数。请注意,回退函数不符合标准,它无法使用已知参数预填充或curry函数。在ES3引擎上运行时,最接近ES5规范。此外,绑定函数不会授予调用方的变量或词法环境的访问权限(OP最后似乎希望这样),它只能确保此
值(和当前参数)将被持久化。