我读了一些文章,文章说下面的2行也在做同样的事情。
fn.call(thisValue);
Function.prototype.call.call(fn, thisValue);
对于线路1,我的理解是,Javascript中的每个函数对象都有一个继承自Function.prototype
的方法call
,而call
方法所做的是将fn
的函数定义中的this
关键字设置为thisValue
(我在调用方法中传递的第一个参数。fn
是一个函数,所以我在fn.call(thisValue)
中所做的只是调用fn
,并将函数中的this
关键字设置为thisValue
。
但对于第2行,我不明白。有人能解释一下第2行的黑客行为吗。
让我们从这个设置开始:
function fn() { console.log(this); }
var thisvalue = {fn: fn};
现在您肯定知道thisvalue.fn()
是一个方法调用,并将记录的this
值设置为thisvalue
对象。
接下来,您似乎知道fn.call(thisvalue)
执行完全相同的调用。或者,我们可以将(thisvalue.fn).call(thisvalue)
(括号仅用于结构,可以省略)写成thisvalue.fn === fn
:
thisvalue.fn(…); // is equivalent to
(thisvalue.fn).call(thisvalue, …); // or:
(fn).call(thisvalue, …);
可以,但fn.call(…)
也只是一个方法调用——函数的call
方法是在fn
函数上调用的
它可以这样访问,因为所有函数对象都继承了Function.prototype
的.call
属性——它不像thisvalue
对象上的.fn
那样是自己的属性。然而,fn.call === Function.prototype.call
与thisvalue.fn === fn
是相同的。
现在,我们可以用.call()
:将.call
的方法调用重写为显式调用
fn.call(thisvalue); // is equivalent to
(fn.call).call(fn, thisvalue); // or:
(Function.protoype.call).call(fn, thisvalue);
我希望你能发现这种模式,现在可以解释为什么下面的工作也一样:
Function.prototype.call.call.call(Function.prototype.call, fn, thisvalue);
var call = Function.prototype.call; call.call(call, fn, thisvalue);
对此进行分解留给读者练习:-)
由于我在这里试图理解这个问题,我也将在这里发布我的答案。
让我们从这个开始:
function fn() { console.log(this); }
fn.a = function(){console.log(this)} // "this" is fn because of the . when calling
fn.a() // function fn() { console.log(this); }
因此,让我们深入挖掘并尝试重新实现call
功能:
Function.prototype.fakeCall = function () {
// taking the arguments after the first one
let arr = Array.prototype.slice.call(arguments, 1);
try{
return this.apply(arguments[0], arr);
}catch(e){}
}
function a(ar){ console.log(ar + this.name) };
let obj = {name : "thierry"};
// a.fakeCall( obj, 'hi ')
Function.fakeCall.fakeCall(a, obj, 'hi ');
因此,当我们这样做时:Function.prototype.fakeCall.fakeCall(a, obj, 'hi ')
实际情况是,在我们的第一次运行中:
arr = [ obj, 'hi ']
this = Function.fakeCall
所以我们最终得到了Function.fakeCall.apply(a, [ obj, 'hi ']);
然后在第二次运行时,我们有
arr = ['hi']
this = a
所以我们最终得到了a.apply(obj, ['hi'])
,它与a.call(obj, 'hi');
相同
源