Search code examples
javascriptobjectparameter-passinginstance-variables

Why does passing a JavaScript object's method not update the object?


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?


Solution

  • 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));