Function.prototype.call 内部实现探讨

今天在网上看到了一个有意思的js题目,就拿去和同事讨论。本来以为是一个很简单的问题,但越讨论越深入,逐步认识到了这个问题的深度。

题目是这样的:

function f1(){
    alert(1);
}
function f2(){
    alert(2);
}
var f3 = f1.call;
f3.call(f2);
 

 

 讨论的过程就不在赘述了,最后的结论是:

1 Function.prototype.call 实现的时候与是依赖与this的,如果直接调用f3(),浏览器将会报错。这个特性跟document.getElementById类似,比如在FF下,$=document.getElementById,调用$时浏览器会报错。

 

2 同样的对函数实例的call调用,如Function.prototype.call()与Function.prototype.call.call(Function.prototype与Function.prototype.call都是Function的实例),Function.prototype.call()可以正常调用,Function.prototype.call.call()则会抛出异常。

 

3 结合结论2以及题目本身,猜测是js引擎对call做了不同的实现,伪码如下:

 

var call = function(a,b,c){
    this(b,c);//忽略this内部实现与a的绑定;
}
call.call = function(a,b,c){
    a(b,c);//忽略this的绑定
}
Function.prototype.call = call;

 这里猜测的是call本身作为Function的一个实例,在对call.call调用的时候,它的实例属性覆盖了它的原型属性。

 

4 但是通过比对 Function.prototype.call === Function.prototype.call.call 是为true的,所以结论3是错误的。应该是js内部为call的实现做了一个统一的托管,根据调用对象的不同,实现不同的逻辑。伪码如下:

 

function call(a,b,c){
    if(this === call){
        a(b,c);
    }else{
        this(b,c);
    }
}
Function.prototype.call = call;

 

 

以上代码都最大化的做了简化,忽略了this的绑定以及参数的传递,只为了简单说明,请勿深究。有不妥的地方,欢迎拍砖。

 

其实这个结论4也不太准确,在我的另一篇博文http://rt0d.iteye.com/blog/1003754中,给出了证明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值