函数式编程-Javascript Function.protype.call()



我读了一些文章,文章说下面的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.callthisvalue.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 ')

实际情况是,在我们的第一次运行中:

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

所以我们最终得到了Function.fakeCall.apply(a, [ obj, 'hi ']);

然后在第二次运行时,我们有

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

所以我们最终得到了a.apply(obj, ['hi']),它与a.call(obj, 'hi'); 相同

最新更新