简体   繁体   English

Javascript Function.prototype.call()

[英]Javascript Function.prototype.call()

I read some article and it said the following 2 line are doing the same thing. 我读了一些文章,它说下面的两行正在做同样的事情。

fn.call(thisValue);
Function.prototype.call.call(fn, thisValue);

For line 1, my understanding is that every function object in Javascript do have a the method call inherited from the Function.prototype and what call method does is to have the this keyword inside the function definition of fn to be thisValue (the first parameter I passed in the call method. fn is a function so what I am doing in fn.call(thisValue) is just invoking fn and set the this keyword inside the function to be thisValue . 对于第1行,我的理解是Javascript中的每个函数对象都具有从Function.prototype继承的方法call ,而call方法所做的是将fn函数定义内的this关键字设为thisValue (第一个参数I fn是一个函数,所以我在fn.call(thisValue)fn.call(thisValue)只是调用fn并将函数内的this关键字设置为thisValue

But For line 2, I don't get it. 但是对于第二行,我不明白。 Can someone help to explain it what the hack the line 2 is doing. 有人可以帮忙解释一下2号线在做什么。

Let's start with this setup: 让我们从此设置开始:

function fn() { console.log(this); }
var thisvalue = {fn: fn};

Now you surely understand that thisvalue.fn() is a method call, and sets the logged this value to the thisvalue object. 现在,您肯定知道thisvalue.fn()是一个方法调用,并将记录的this值设置为thisvalue对象。

Next, you seem to know that fn.call(thisvalue) does exactly the same call. 接下来,您似乎知道fn.call(thisvalue)完全相同的调用。 Alternatively, we could write (thisvalue.fn).call(thisvalue) (parentheses just for structure, could be omitted) as thisvalue.fn === fn : 或者,我们可以写成(thisvalue.fn).call(thisvalue) (仅用于结构的括号,可以省略)为thisvalue.fn === fn

thisvalue.fn(…); // is equivalent to
(thisvalue.fn).call(thisvalue, …); // or:
(fn).call(thisvalue, …);

OK, but fn.call(…) is just a method call as well - the call method of functions is called on the fn function. 可以,但是fn.call(…)也是方法调用-在fn函数上call函数的call方法
It can be accessed as such because all function objects inherit this .call property from Function.prototype - it's not an own property like .fn on the thisvalue object. 它可以作为这样的,因为所有的函数对象继承此访问.call物业Function.prototype -它不是自己的财产一样.fnthisvalue对象。 However, fn.call === Function.prototype.call is the same as thisvalue.fn === fn . 但是, fn.call === Function.prototype.callthisvalue.fn === fn相同。

Now, we can rewrite that method call of .call as an explicit invocation with .call() : 现在,我们可以将.call方法调用重写为.call()的显式调用:

fn.call(thisvalue); // is equivalent to
(fn.call).call(fn, thisvalue); // or:
(Function.protoype.call).call(fn, thisvalue);

I hope you spot the pattern and can now explain why the following work as well: 我希望您能发现这种模式,并且现在可以解释以下原因为何:

Function.prototype.call.call.call(Function.prototype.call, fn, thisvalue);
var call = Function.prototype.call; call.call(call, fn, thisvalue);

Breaking this down is left as an exercise to the reader :-) 分解下来留给读者练习:-)

Since I ended up here trying to understand this question , I'm gonna post my answer here as well. 由于我最终在这里试图理解这个问题 ,因此我也将在这里发布答案。

Let's start with this: 让我们从这个开始:

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); }

So let's dig deeper and try to reimplement the call function: 因此,让我们更深入地尝试重新实现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 ');

Thus when we do this: Function.prototype.fakeCall.fakeCall(a, obj, 'hi ') 因此,当我们这样做时: Function.prototype.fakeCall.fakeCall(a, obj, 'hi ')

what happens is, on the first run we have: 发生的是,在第一次运行中,我们有:

  1. arr = [ obj, 'hi ']
  2. this = Function.fakeCall

so we end up with Function.fakeCall.apply(a, [ obj, 'hi ']); 所以我们最后得到Function.fakeCall.apply(a, [ obj, 'hi ']);

Then on the second run we have 然后在第二轮

  1. arr = ['hi']
  2. this = a

so we end up with a.apply(obj, ['hi']) which is the same as a.call(obj, 'hi'); 所以我们最终得到a.apply(obj, ['hi'])a.call(obj, 'hi');

source 资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM