with eval and this

witheval 已经够麻烦了,被归到 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); });
   

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值