0
'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 ?

1

2 Answers 2

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!

Sign up to request clarification or add additional context in comments.

1 Comment

Excellent. Thank you !
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.

2 Comments

Thanks for introducing the desugaring concept. I was not aware of it before. The line marked with ** will desugar to this.func.call(this, x). This is invalid per Terry's point above. Hence we need to call the primitive ourself.
By the way, if anyone else is unfamiliar with desugaring read this blog: yehudakatz.com/2011/08/11/…. It helped me a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.