Understanding the JavaScript “this” keyword: Part 2

In the previous article, we uncovered the fundamental rules around how the value of this is determined when inside a function. If you haven’t read it yet, head over to the first article, and pop back here when you’re done.

From this point onwards, we’re going to explore a number of JavaScript features that throw those rules out of the window, and allow the caller to choose the value of this.

  1. Changing the value of this using call() and apply()We know if you call someObject.foo() that this inside foo will be someObject. What if we want it to be anotherObject?

    Well, we could do this;

    anotherObject.foo = someObject.foo;
    anotherObject.foo();
    delete anotherObject.foo;

    Bit of a hack, no? Enter call() and apply(). All you have to do is;

    someObject.foo.call(anotherObject);

    What if you want to pass arguments to foo() as well? No problem!

    someObject.foo.call(anotherObject, 1, 2, "abc");

    apply() works exactly the same, but the difference is how they let you pass arguments to the function. call() expects each argument as a separate parameter, whereas apply() expects a single array, whose elements are all the parameters. The equivalent apply() call for the above would be;

    someObject.foo.apply(anotherObject, [1, 2, "abc"]);
  2. Forcing the value of this using bind()bind() is a tricky addition to the JavaScript language (introduced in ES5). If you call someObject.foo.bind(anotherObject), bind() will return a new function; and no matter how you call the returned function (even using call() and apply()), the value of this will always be anotherObject.
    var obj = {
        val: 4
    };
    
    function foo() {
        alert(this.val);
    }
    
    var bar = foo.bind(obj);
    
    foo(); // behaves as expected; alerts `undefined` as `foo` is not attached to an object
    bar(); // breaks the rules! alerts `4` because `bind()` sets `this` to `obj`.
    
    bar.call(window); // this has no effect; still alerts `4`.

    Try it yourself!

    You might wonder how bind() works; but even if ES5 hadn’t included bind(); well, we could roll out our own really easily;

    Function.prototype.ourBind = function(thisArg) {
        var that = this;
    
        return function() {
            return that.apply(thisArg, arguments);
        };
    };

    We could then use ourBind() exactly how we’d use bind(); see it in action on jsFiddle!

  3. The new keyword has the last say…One last feature in JavaScript that I’d like to mention before finishing this article is the new keyword.

    If you’re not quite clued up on the behaviour of new you can read more about it here.

    Using new when calling a function is the final way to change the value of this when calling a function. When you use new, this points to a new object, whose “prototype” is set to the prototype of the function you called new on. Yep; that might take a few reads to sink in.

    The only use case for this is when creating instances of a object; but I just wanted to complete the list of “ways-this-can-be-changed”.

That concludes the articles on this; I hope you now have a much better understanding about how it works! If you want to read a few more articles to help it sink in, I’d recommend this quirksmode article and this Stack Overflow question

Leave a Reply

Your email address will not be published. Required fields are marked *