Understanding javascript call function

时间:2018-04-18 17:55:38

标签: javascript

'use strict';

let worker = {
  someMethod() {
    return 4;
  },

  slow(x) {
    return x * this.somemethod();
  }
};

function wrapper(func) {
  return function(x) {
    let result = this.func(x);  // **
    return result;
  };
}

worker.slow = wrapper(worker.slow);
alert( worker.slow(2) );

When I run this code I get this error:

  TypeError:  this.func is not a function

If I replace the problematic line at ** with this:

let result = func.call(this, x);

I get the expected output. In this case it's 8.

I'm wondering why the way it's written is the wrong way to get "this" ie the object worker. In other words, how does the call function get the right object i.e. worker ?

2 个答案:

答案 0 :(得分:3)

The reason it's failing is that in the problematic line (highlighted with // **), you're effectively calling worker.func(x), which does not exist; You're not referring to the passed in variable at all.

If you add a function (func) to your worker, e.g.

let worker = {
  someMethod: function() {
    return 4;
  },

  slow: function(x) {
    return x * this.somemethod();
  },
  func: function (x) {
     return x * 10;
  }
};

And call as above e.g.

worker.slow = wrapper(worker.slow);
console.log( worker.slow(2) );

You'd find it works, though this is not what you really want!

答案 1 :(得分:2)

In JavaScript, any function call obj.f(ArgumentList) will be desugared into f.call(obj, ArgumentList...)(see ecma-262 7.3.12)

When wrapper(worker.slow) got a call, the function slow is passed into the wrapper and it produces another function which captured func argument. However, that function returned by wrapper is not called yet.

At a moment of the function call alert( worker.slow(2) ) func mean the argument that got captured in the closure and func.call(this, x) means it will call that function with the current caller, which is worker.

Therefore, `func.call(this,x)` will be `func.call(worker, x) `
which works because `func` exists in the closure.

while this means the reference to a current caller to the function(x){ ... }

Hence, `this.func(x)` will be `worker.func(x)` 
which `func` does not exist in `worker`.

if you try to insert console.log(func) and console.log(this) in that function, you will see the difference.