试分析以下代码的执行过程:
var each=Function.prototype.call.bind([].forEach);
each(document.querySelectorAll(‘li’),fn);
(1)重新理解f.call(a,b,c);的执行过程
首先我们看到f.call也是一个函数,
而且任何一个函数f都有这个属性call,它来自Function.prototype.call。
这个函数的执行过程如下:
让f中的this指向a,然后用[b,c]作为参数进行调用。
可是,call这个函数是怎么拿到f的呢?
这就要通过call函数的this了。
所以,完整的执行过程应该如下:
让call函数的this所指向的函数中的this指向a,然后用[b,c]作为参数进行调用。
(2)var g=f.bind(a);
<u></u>bind返回一个新函数,这个函数调用结果相当于把f中的this指向a再进行调用。
Function.prototype.bind=function(a){
var fn=this;
return function(){
fn.apply(a,arguments);
};
};
(3)var each=Function.prototype.call.bind([].forEach)
<u></u>each的调用结果相当于,把call函数中的this指向[].forEach再进行调用。
(4)each(document.querySelectorAll(‘li’),fn);
首先each是一个call函数,只不过this固定为了[].forEach。
根据call函数的调用规则:
让call函数的this所指向的函数中的this指向a,然后用[b,c]作为参数进行调用。
=>让[].forEach中的this指向document.querySelectorAll('li'),然后用[fn]作为参数进行调用。
=>[].forEach.call(document.querySelectorAll(‘li’),fn);
注:
<u></u>forEach回调函数中的this指向window
[1,2].forEach(function(v,i){console.log(this,v,i);});
> [window] 1 0
> [window] 2 1
[].forEach.call([1,2],function(v,i){console.log(this,v,i);});
> [window] 1 0
> [window] 2 1