0

I noticed that when passing an object's method (which updates one of the object's own properties) as an argument to another function, the original object will not be modified.

For example:

var obj = {
    foo: 0,
    bar: function () {
        this.foo++;
    }
};

function baz(callback) {
    callback();
}

baz(obj.bar); // does not alter obj
obj.bar(); // increments obj.foo successfully
console.log(obj.foo); // should be 2, not 1

Why is this, since JavaScript objects are passed by reference?

reformed
  • 3,922
  • 9
  • 51
  • 77
  • See here: http://stackoverflow.com/questions/3630054/how-do-i-pass-the-this-context-to-a-function – Dai Jan 10 '17 at 17:37

2 Answers2

2

This is because the context - or this value - of a function is based on how it's called, not on how it's defined. Your bar function doesn't know it's inside the obj object.

When you do obj.bar();, you are calling it in the context of obj, thus this is what you expect.

When you do baz(obj.bar);, you are passing the bar function as a parameter. It no longer has any ties to the obj object. Remember, functions can be treated like variables. So, when baz runs its callback, it's ran in the "global" context (this is window).

The solution here is to use .bind() to "lock in" the this value.

baz(obj.bar.bind(obj));
Rocket Hazmat
  • 204,503
  • 39
  • 283
  • 323
0

Because you need to bind the callback to a specific object.

baz(obj.bar.bind(obj));

Functions are only automatically bound to the object before . when you perform the call in the same expression. Simply accessing the property doesn't bind it.

Barmar
  • 596,455
  • 48
  • 393
  • 495