不能直接使用Function.prototype.call

时间:2017-06-12 01:22:59

标签: javascript

function f(a) { return a}

f(1) // => 1

f.call(null, 1) // => 1

Function.prototype.call(f, null, 1) // => undefined

为什么最后一行返回undefined,我认为它们是相同的。

2 个答案:

答案 0 :(得分:2)

这些将是相同的:

function f(a) { return a}

console.log(f(1)); // => 1

console.log(f.call(null, 1)); // => 1

console.log(Function.prototype.call.call(f, null, 1)); // => 1

这是一个解释:

Function.prototype.call

根据specFunction.prototype.call返回抽象操作 Call(func,thisArg,argList)

因此,f.call(null, 1)将返回抽象操作 Call(f,null,1)其中 f 是被调用的函数, null < / em>是调用它的上下文, 1 是传递给 f 的参数。这将为您提供所需的输出。

基于此,Function.prototype.call(f, null, 1)将导致抽象操作调用(Function.prototype,f,null,1)其中 Function.prototype 是调用函数, f 是上下文, null 1 是传递给 Function.prototype 的参数。当然,这不会按预期工作。

Function.prototype.call.call

但是,Function.prototype.call.call(f, null, 1)将返回抽象调用操作 Call(Function.prototype.call,f,null,1),其中 Function.prototype.call 是要调用的函数, f 是调用它的上下文 null 1 作为参数传递。

那会是什么样子?

好吧,因为 f 是上下文而调用是用(null,1)调用的函数,所以最终结果是相同的致:f.call(null, 1)

答案 1 :(得分:2)

让我们从这开始:

function fn() { console.log(this); }
fn.a = function(){console.log(this)}
fn.a() // function fn() { console.log(this); }

因此,让我们深入挖掘并尝试实现假call函数:

  Function.prototype.fakeCall = function () {
    // console.log(this)
    // taking the arguments after the first one
    let arr = Array.prototype.slice.call(arguments, 1);
    // on the first run this will be Function.fakeCall but on the second pass it will be the first argument (the a function)
    this.apply(arguments[0], arr);
  }

  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.   
  3. this = Function.fakeCall
  4.   

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

然后在第二轮比赛中我们

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

因此我们最终得到的a.apply(obj, ['hi'])a.call(obj, 'hi');

相同

但是,如果我们Function.fakeCall(a, obj, 'hi '); 在第一次运行时,我们将this = Function,这将无法正常工作。在这种情况下它会抛出一个错误,在你的情况下它只返回undefined。这可以通过try-catch轻松实现。

  Function.prototype.fakeCall = function () {
    let arr = Array.prototype.slice.call(arguments, 1);
    try{
       return this.apply(arguments[0], arr);
    }catch(e){}
  }

  function a(ar){ return ar + this.name };
  let obj = {name : "thierry"};
  console.log(Function.fakeCall(a, obj, 'hi ')); // undefined

  console.log(Function.fakeCall.fakeCall(a, obj, 'hi ')); // hi thierry