不错,接下来再理解一个怪异的形式
function f1(){
alert(1);
}
function f2(){
alert(2)
}
var f3 = f1.call;
f1.call(f2);//1
f3.call(f2);//2
f1.call(f2); 比较好理解,如果不理解看上边的case,但如何理解f3.call(f2) 会返回2呢,为了方便理解进行一下等效变化为f1.call.call(f2) ,这时会发现实际上是 f1.call 方法 call 调用了 f2 ,那 f1 怎么又会有 call 方法呢? call , apply 都属于Function.prototype 的一个方法,它是 JavaScript 引擎内在实现的,因为属于Function.prototype ,所以每个 Function 对象实例,也就是每个方法都有call , apply 属性。
在理解 f1.call.call(f2) 时我们首先要知道 call 方法到底是如何执行的,这样才能 f1.call.call(f2) 如何执行。
引用JK写的一个用apply实现call的方法:
function jsCall(oThis){//这里的jsCall就是Call
var argsNew = [];
for(var i=1;i<arguments.length;i++){
argsNew.push(arguments[i]);
}
return this.apply(oThis,argsNew);
}
Function.prototype.jsCall = jsCall;
或简写成
function jsCall(oThis){//这里的jsCall就是Call
var argsNew = [].slice.call(arguments,1)
return this.apply(oThis,argsNew);
}
Function.prototype.jsCall = jsCall;
这样就得到了一个和 call 一样功能的 jsCall , 接下来构建两个函数 f1 ,f2
function f1(a){
alert([this,a,'f1']);
}
f1(11);//[object Window],11,f1
function f2(a){
alert([this,a,'f2']);
}
f2(22);//[object Window],22,f2
用 jsCall 把 f1 中的 this 替换成 f2
function f1(a){
alert([this,a,'f1']);
}
function f2(a){
alert([this,a,'f2']);
}
f1.jsCall(f2,11);//function f2(a){alert([this, a, "f2"]);},11,f1
执行结果发现 [object Window] 被替换成 f2 函数
function jsCall(oThis){//这里的jsCall就是Call
var argsNew = [].slice.call(arguments,1)
return this.apply(oThis,argsNew);
}
Function.prototype.jsCall = jsCall;
function f1(a){
alert([this,a,'f1']);
}
function f2(a){
alert([this,a,'f2']);
}
f1.jsCall.jsCall(f2,11);//11,,f2
在执行 f1.jsCall.jsCall(f2,11); 时返回 11,,f2 ,为什么会返回这个结果,重点来了:)
f1.jsCall 方法:
alert(f1.jsCall);
//返回
//function jsCall(oThis) {
// var argsNew = [].slice.call(arguments, 1);
// return this.apply(oThis, argsNew);
//}
所以 f1.jsCall.jsCall 可以替换成 jsCall.jsCall 看一下执行结果
function jsCall(oThis){//这里的jsCall就是Call
var argsNew = [].slice.call(arguments,1)
return this.apply(oThis,argsNew);
}
Function.prototype.jsCall = jsCall;
function f1(a){
alert([this,a,'f1']);
}
function f2(a){
alert([this,a,'f2']);
}
jsCall.jsCall(f2,11);//11,,f2
接着分析
jsCall 在执行的过程中, return this.apply(oThis,argsNew); 里的this 被替换成了
f2 , 11 做为参数传给了 (oThis,argsNew) ,变成了 f2.apply(11);
function jsCall(oThis){//这里的jsCall就是Call
var argsNew = [].slice.call(arguments,1)
return this.apply(oThis,argsNew);
}
Function.prototype.jsCall = jsCall;
function f1(a){
alert([this,a,'f1']);
}
function f2(a){
alert([this,a,'f2']);
}
f2.apply(11);//11,,f2
返回结果跟 f1.jsCall.jsCall(f2,11) 一样。
回过头来看
function f1(){
alert(1);
}
function f2(){
alert(2)
}
var f3 = f1.call;
f1.call(f2);//1
f3.call(f2);//2
这样就不难理解 f1.call.call(f2) 实现时, f1.call 执行过程中 call 中的 this 被 f2 替换成了
f2.call(); 因为 f2 里没有 this 的引用所以执行结果是2.
f2.call()//2
需要十分注意的是 f1.call 是方法, f1 是函数对象,这两者在 call 时是有区别的。