with ,eval 已经够麻烦了,被归到 bad parts 后总算减轻点负担,但如果确实使用了 eval,则要考虑下 this 是否受到影响.
this:
在 google 代码规范 中提及到 this 的指向有5种情况:
1.大多数情况指向全局对象,在浏览器环境下就是 window
2.在 eval 中指向 the scope of the caller
3.在 dom1 事件绑定中指向绑定的元素,dom2 标准浏览器也是。
4.在apply,call调用下指向参数
5. 构造器中指向新生成对象
eval :
特别是 2 ,其实这里需要仔细说下,应该不是直接指向调用者所用域,而是和调用者作用域中存在的 this 相同才是。
当在函数中直接 eval 时:
function x(){
eval("console.log(this)");
}
x();
x.apply({y:1});
根据规范解释:eval 中的 this 和 caller 调用者的 this 相同,上面即相当于,直接:
function x(){
console.log(this);
}
但是有点需要注意的是,当间接使用 eval 时,情况就不一样了 :
var y=eval;
function x(){
y("console.log(this)");
}
x();
x.apply({y:1});
在 webkit 下 this 都指向全局对象 window,而 firefox 则和直接使用 eval 一样,但同时两者在别名情况下执行代码串都丢失了作用域链的信息(这也正是这种写法的主要应用场景,脱离作用域链 )。
不过 IE 却又和 webkit,firefox 有区别,当使用别名 eval 时,这时和直接使用 eval 完全没有区别,作用域链仍然在,this 依然和调用者保持一致,怪异。
这种情况的解释目前尚未找到正式描述。
建议是不要使用直接别名引用,可以 work around by this :
function foo(v){
eval(v)
}
但是这里又有点需要注意的地方,v 参数里面不要再引用到 v,否则引用到自身代码打印出来
function foo(v){
eval(v)
}
var v=1;
//woo! surprise
foo("alert(v);");
所以最好还是使用 new Function 来执行吧:
var v=1;
new Function("alert(this.v);").call({v:2});
若不使用 call 以及 apply ,this 始终指向 window ,作用域链丢失。
终极混合测试:
终极就要达到茴字有几种写法的效果:
var v='outer_v',foo=eval,
foo2=function(v2){
eval(v2);
},
x='outer_x';
(function (context,fn) {
with (context) {
foo2("("+fn+").call(this);");
foo("("+fn+").call(this);");
eval("("+fn+").call(this);");
new Function("("+fn+").call(this);")();
}
}).call({x:'this_x'},{ v: 'inner_v' }, function () { alert(v);alert(this.x); });
1689

被折叠的 条评论
为什么被折叠?



