Seven JavaScript Quirks I Wish I’d Known About

JavaScript_quirks_header

If you are new to JavaScript or it has only been a minor part of your development effort until recently, you may be feeling frustrated. All languages have their quirks – but the paradigm shift from strongly typed server-side languages to JavaScript can feel especially confusing at times. I’ve been there! A few years ago, when I was thrust into full time JavaScript development, there were many things I wish I’d known going into it. In this article, I’ll share a few of these quirks in hopes that I might spare you some of the headaches I endured. This isn’t an exhaustive list – just a sampling – but hopefully it will shed some light on the language as well as show how powerful it can be once you get past these kinds of hurdles.

The Quirks We’ll look at:

  1. Equality
  2. Dot Notation vs Bracket Notation
  3. Function Context
  4. Function Declarations vs Function Expressions
  5. Named vs Anonymous Functions
  6. Immediately Invoked Function Expressions
  7. typeof vs Object.prototype.toString

1.) Equality

Coming from C#, I was well familiar with the == comparison operator. Value types (& strings) are either equal (have the same value) or they aren’t. Reference types are either equal – as in pointing to the same reference – or NOT. (Let’s just pretend you’re not overloading the == operator, or implementing your own Equals and GetHashCode methods.) I was surprised to learn that JavaScript has two equality operators: == and ===. Most of the code I’d initially seen used ==, so I followed suit and wasn’t aware of what JavaScript was doing for me as I ran code like this:

var x = 1;

if(x == "1") {
    console.log("YAY! They're equal!");
}

So what dark magic is this? How can the integer 1 equal the string “1”?

In JavaScript, there’s equality (==) and then there’s strict equality (===). The equality comparison operator will coerce the operands to the same type and then perform a strict equality comparison. So in the above example, the string “1” is being converted, behind the scenes, to the integer 1, and then compared to our variable x.

Strict equality doesn’t coerce the types for you. If the operands aren’t of the same type (as in the integer 1 and string “1”), then they aren’t equal:

var x = 1;

// with strict equality, the types must be the *same* for it to be true
if(x === "1") {
    console.log("Sadly, I'll never write this to the console");
}

if(x === 1) {
    console.log("YES! Strict Equality FTW.")
}

You might already be thinking of the kinds of horrors that could occur when type coercion is done for you – the sort of assumptions that you could make that misrepresent the true nature of the values in your app which lead to difficult-to-find-yet-hiding-in-plain-sight bugs. It’s no surprise, then, that the general rule of thumb recommended by experienced JavaScript developers is to always use strict equality.

2.) Dot Notation vs Bracket Notation

Depending on what other languages you hail from, you probably weren’t too surprised to see these forms of accessing a property on an object and accessing an element in an array in JavaScript:

// getting the "firstName" value from the person object:
var name = person.firstName;

// getting the 3rd element in an array:
var theOneWeWant = myArray[2]; // remember, 0-based index

However, did you know it’s possible to use bracket notation to reference object members as well? For example:

var name = person["firstName"];

Why would this be useful? While you’ll probably use dot notation the majority of the time, there are a few instances where bracket notation makes certain approaches possible that couldn’t be done otherwise. For example, I will often refactor large switch statements into a dispatch table, so that something like this:

var doSomething = function(doWhat) {
    switch(doWhat) {
        case "doThisThing":
            // more code...
        break;
        case "doThatThing":
            // more code...
        break;
        case "doThisOtherThing":
            // more code....
        break;
        // additional cases here, etc.
        default:
            // default behavior
        break;
    }
}

Can be transformed into something like this:

var thingsWeCanDo = {
    doThisThing      : function() { /* behavior */ },
    doThatThing      : function() { /* behavior */ },
    doThisOtherThing : function() { /* behavior */ },
    default          : function() { /* behavior */ }
};

var doSomething = function(doWhat) {
    var thingToDo = thingsWeCanDo.hasOwnProperty(doWhat) ? doWhat : "default"
    thingsWeCanDo[thingToDo]();
}

There’s nothing inherently wrong with using a switch (and in many cases, if you’re iterating and performance is a huge concern, a switch may outperform the dispatch table). However, dispatch tables offer a nice way to organize and extend behavior, and bracket notation makes it possible by allowing you to reference a property dynamically at runtime.

3.) Function Context

There have been a number of great blog posts about properly understanding the “this context” in JavaScript (and I’ll link to several at the bottom of this post), but it definitely makes my list of “things I wish I’d known” right away. It’s really not difficult to look at code and confidently know what this is at any point – you just have to learn a couple of rules. Unfortunately, many explanations I read about it early on just added to my confusion. As a result, I’ve tried to simplify the explanation for developers new to JavaScript.

First – Start With a Global Assumption

By default, until there’s a reason for the execution context to change, this refers to the global object. In the browser, that would be the window object (or global in node.js).

Second – the Value of this in Methods

When you have an object with a member that is a function, invoking that method from the parent object makes this the parent object. For example:

var marty = {
    firstName: "Marty",
    lastName: "McFly",
    timeTravel: function(year) {
        console.log(this.firstName + " " + this.lastName + " is time traveling to " + year);
    }
}

marty.timeTravel(1955);
// Marty McFly is time traveling to 1955

You might already know that you can take the marty object’s timeTravel method and create a new reference to it from another object. This is actually quite a powerful feature of JavaScript – enabling us to apply behavior (functions) to more than one target instance:

var doc = {
    firstName: "Emmett",
    lastName: "Brown",
}

doc.timeTravel = marty.timeTravel;

So – what happens if we invoke doc.timeTravel(1885)?

doc.timeTravel(1885);
// Emmett Brown is time traveling to 1885

Again – deep dark magic. Well, not really. Remember, when you’re invoking a method, the this context is the parent object it’s being invoked from. Hold on to your DeLoreans, though, cause it’s about the get heavy.

(Note: I’ve updated this section for clarity and to make some corrections from the original post.)

What happens when we save a reference to the marty.TimeTravel method and invoke our saved reference? Let’s look:

var getBackInTime = marty.timeTravel;
getBackInTime(2014);
// undefined undefined is time traveling to 2014

Why “undefined undefined”?! Why not “Marty McFly”?

Let’s ask an important question: What’s the parent/owning object when we invoke our getBackInTime function? While the getBackInTime function will technically exist on the window, we’re invoking it as a function, not a method of an object. When we invoke a function like this – with no owning object – the this context will be the global object. David Shariff has a great way of describing this:

Whenever a function is called, we must look at the immediate left side of the brackets / parentheses “()”. If on the left side of the parentheses we can see a reference, then the value of “this” passed to the function call is exactly of which that object belongs to, otherwise it is the global object.

Since getBackInTime‘s this context is the window – which does not have firstName and lastName properties – that explains why we see “undefined undefined”.

So we know that invoking a function directly – no owning object – results in the this context being the global object. But I also said that I knew our getBackInTime function would exist on the window. How do I know this? Well, unless I’ve wrapped the getBackInTime in a different scope (which we’ll investigate when we discuss immediately-invoked-function-expressions), then any vars I declare get attached to the window. Here’s proof from Chrome’s console:

jsquirks_afjq_1

This is the perfect time to talk about one of the main areas that this trips up developers: subscribing event handlers.

Third (really just an extension of #2) – The Value of this in Methods When Invoked Asynchronously

So, let’s pretend we want to invoke our marty.timeTravel method when someone clicks a button:

var flux = document.getElementById("flux-capacitor");
flux.addEventListener("click", marty.timeTravel);

With the above code, when the user clicks the button, we’ll see “undefined undefined is time traveling to [object MouseEvent]”. WAT?! Well – the first, and most obvious, issue is that we’re not providing the year argument to our timeTravel method. Instead, we subscribed the method directly as an event handler, and the MouseEvent argument is being passed to the event handler as the first arg. That’s easy to fix, but the real issue is that we’re seeing “undefined undefined” again. Don’t despair – you already know why this is the case (even if you don’t realize it yet). Let’s make a change to our timeTravel function to log whatever this is to help give us some insight:

marty.timeTravel = function(year) {
    console.log(this.firstName + " " + this.lastName + " is time traveling to " + year);
    console.log(this);
};

Now – when we click the button, we should see something similar to the following output in our browser console:

jsquirks_afjq_2

Our second console.log shows us the this context when the method was invoked – and it’s the actual button element which we subscribed to. Does this surprise you? Just like earlier – when we assigned the marty.timeTravel reference to our getBackInTime var – a reference to marty.timeTravel was saved as our event handler and is being invoked, but not from the “owning” marty object. In this case, it’s being invoked asynchronously by the underlying event emitting implementation of the button element instance.

So – is it possible make this what we want it to be? Absolutely! In this case, the solution is deceptively simple. Instead of subscribing marty.timeTravel directly as the event handler, we can use an anonymous function as our event handler, and call marty.timeTravel from within it. This also provides the opportunity to fix our issue with the missing year parameter.

flux.addEventListener("click", function(e) {
    marty.timeTravel(someYearValue); 
});

Clicking the button now will result in something similar to this output on the console:

jsquicks_afjq_3

Success! But why did this work? Think of how we’re invoking the timeTravel method. In our first button click example, we subscribed the method reference itself as the event handler, so it was not being called from the parent object of marty. In the second example, it’s our anonymous function that will have a this of the button element, and when we invoke marty.timeTravel, we’re calling it from the marty parent object, and the this will be marty.

Fourth – The Value of this Inside Constructor Functions.

When you use a constructor function to create a new instance of an object, the this value inside the function is the new object that’s being created. For example:

var TimeTraveler = function(fName, lName) {
    this.firstName = fName;
    this.lastName = lName;
    // Constructor functions return the
    // newly created object for us unless
    // we specifically return something else
};

var marty = new TimeTraveler("Marty", "McFly");
console.log(marty.firstName + " " + marty.lastName);
// Marty McFly

Using Call, Apply & Bind

You might already suspect, given the above examples, that there might be some language-level features that would allow us to invoke a function and tell it at runtime what this should be. You’d be right. The call and apply methods that exist on the Function prototype both allow us to invoke a function and pass in a this value.

call‘s method signature takes the this arg, followed by the parameters the function being invoked would take as separate arguments:

someFn.call(this, arg1, arg2, arg3);

`apply` takes `this` as the first arg, followed by an array of the remaining arguments:

someFn.apply(this, [arg1, arg2, arg3]);

Our `doc` and `marty` instances can time travel on their own, but Einstein needed their help to time travel. So let’s add a method to our `doc` instance from earlier (the one we copied the `timeTravel` method to), so that `doc` can cause an `einstein` instance to travel in time:

doc.timeTravelFor = function(instance, year) {
    this.timeTravel.call(instance, year);
    // alternate syntax if you used apply would be
    // this.timeTravel.apply(instance, [year]);
};

Now it’s possible to send Einstein on his way:

var einstein = {
    firstName: "Einstein", 
    lastName: "(the dog)"
};
doc.timeTravelFor(einstein, 1985);
// Einstein (the dog) is time traveling to 1985

I know this is a contrived example, but it’s enough to give you a glimpse of the power of applying functions to other objects.

There’s still one other possibility we haven’t explored. Let’s give our marty instance a goHome method that’s simply a shortcut to calling this.timeTravel(1985):

marty.goHome = function() {
    this.timeTravel(1985);
}

However, we know that if we subscribe marty.goHome as the event handler to our button’s click event, that this will be the button – and unfortunately buttons don’t have a timeTravel method. We could use our approach from earlier – where an anonymous function was the event handler, and it invoked the method on the marty instance – but we have another option, the bind function:

flux.addEventListener("click", marty.goHome.bind(marty));

The bind function actually returns a new function, with the this value of the new function set to what you provide as the argument. If you’re supporting older browsers (less than IE9, for example), then you’ll need to shim the bind function (or, if you’re using jQuery, you can use $.proxy; both underscore & lodash provide _.bind).

One important thing to remember is that if you use bind on a prototype method, it creates an instance-level method, which bypasses the advantages of having methods on the prototype. It’s not wrong, just something to be aware of. I write more about this particular issue here.

4.) Function Expressions vs Function Declarations

There are two main ways you will typically see functions defined in JavaScript (though ES6 will introduce another)): function declarations and function expressions.

Function Declarations do not require a var keyword. In fact, as Angus Croll says: “It’s helpful to think of them as siblings of Variable Declarations.” For example:

function timeTravel(year) {
    console.log(this.firstName + " " + this.lastName + " is time traveling to " + year);
}

The function name timeTravel in the above example is visible not only inside the scope it was declared, but inside the function itself as well (this is especially useful for recursive function calls). Function declarations are, by nature, named functions. In other words, the above function’s name property is timeTravel.

Function Expressions define a function and assign it to a variable. They typically look like this:

var someFn = function() {
    console.log("I like to express myself...");
};

It’s possible to name function expressions as well – though, unlike function declarations, a named function expression’s name is only accessible inside its scope:

var someFn = function iHazName() {
    console.log("I like to express myself...");
    if(needsMoreExpressing) {
        iHazName(); // the function's name can be used here
    }
};

// you can call someFn() here, but not iHazName()
someFn();

Discussing function expressions and declarations wouldn’t be complete without at least mentioning “hoisting” – where function and variable declarations are moved to the top of the containing scope by the interpreter. We’re not going to cover hoisting here, but be sure to read two great explanations by Ben Cherry and Angus Croll.

5.) Named vs Anonymous Functions

Based on what we’ve just discussed, you might have guessed that an “anonymous” function is a function without a name. Most JavaScript developers would quickly recognize the second argument below as an anonymous function:

someElement.addEventListener("click", function(e) {
    // I'm anonymous!
});

However, it’s also true that our marty.timeTravel method is anonymous as well:

var marty = {
    firstName: "Marty",
    lastName: "McFly",
    timeTravel: function(year) {
        console.log(this.firstName + " " + this.lastName + " is time traveling to " + year);
    }
}

Since function declarations must have a name, only function expressions can be anonymous.

6.) Immediately Invoked Function Expressions

And since we’re talking about function expressions, one thing I wish I’d known right away: the Immediately Invoked Function Expression (IIFE). There are a number of good posts on IIFEs (I’ll list a few at the end), but in a nutshell, it’s a function expression that is not assigned to a variable to be executed later, it’s executed immediately. It might help to see this take shape in a browser console.

First – let’s start with just entering a function expression – but not assigning it – and see what happens:

jsquirks_afjq_4

That’s not valid JavaScript syntax – it’s a function declaration missing its name. However, to make it an expression, we just need to surround it with parentheses:

jsquirks_afjq_6 jsquirks_afjq_5

Making this an expression immediately returns our anonymous function to the console (remember, we’re not assigning it, but since it’s an expression we get its value back). So – we have the “function expression” part of “immediately invoked function expression”. To get the “immediately invoked” aspect, we call what the expression returns by adding another set of parentheses after the expression (just like we’d invoke any other function):

jsquirks_afjq_6

“But wait, Jim! I think I’ve seen this before with the invocation parentheses inside the expression parentheses”. Indeed you probably have – it’s perfectly legal syntax (and is well known to be Douglas Crockford’s preferred syntax):

jsquirks_afjq_7

Either approach on where to put the invocation parentheses is usable, however I highly recommend reading one of the best explanations ever on why & when it could matter.

Ok, great – now we know what an IIFE is – why is it useful?

It helps us control scope – an essential part of any JavaScript endeavor! The marty instance we’ve looked at earlier was created in the global scope. This means that the window (assuming we’re in a browser), will have a marty property. If we write all of our JavaScript code this way, we’ll quickly end up with a metric ton of vars declared in the global scope, polluting the window with our app’s code. Even in the best case scenarios, it’s bad practice to leak that many details into the global scope, but what happens when someone names a variable the same name as an already existing property on the window? It gets overwritten!

For example, if your favorite “Amelia Earhart” fan site declares a navigator variable in the global scope, this is a before and after look at what happens:

jsquirks_afjq_8

OOPS!

Obviously – polluting the global scope is bad. JavaScript utilizes function scope (not block scope, if you’re coming from C# or Java, this is important!), so the way to keep our code from polluting the global scope is to create a new scope, and we can use an IIFE to do this since its contents will be inside its own function scope. In the example below, I’m showing you the window.navigator value in the console, and then I create an IIFE to wrap the behavior and data specific to Amelia Earhart. This IIFE happens to return an object that will serve as our “application namespace”. Inside the IIFE I declare a navigator variable to show that it will not overwrite the window.navigator value.

jsquirks_afjq_9

As an added bonus, the IIFE we created above is the beginnings of a module pattern in JavaScript. I’ll include some links at the end so you can explore module patterns further.

7.) The `typeof` Operator and `Object.prototype.toString`

Eventually, you’ll probably find yourself in a situation where you need to inspect the type of a value passed into a function, or something similar. The typeof operator might seem the obvious choice, however, it’s not terribly helpful. For example, what happens when we call typeof on an object, an array, a string and a regular expression?

jsquirks_afjq_10

Well – at least we can tell our strings apart from objects, arrays and regular expressions, right? Thankfully, we can take a different approach to get more accurate information about type we’re inspecting. We’ll use the Object.prototype.toString function and apply our knowledge of the call method from earlier:

jsquirks_afjq_11

Why are we using the toString on Object.prototype? Because it’s possible for 3rd party libraries, as well as your own code, to override the toString method with an instance method. By going to the Object.prototype, we can force the original toString behavior on an instance.

If you know what typeof will return and you don’t need to check beyond what it will give you (for example, you just need to know if something is a string or not), then using typeof is perfectly fine. However, if you need to tell arrays from objects, regexes from objects, etc., use Object.prototype.toString.

Where to Go Next

I’ve benefitted tremendously from the insights of other JavaScript developers, so please check these links out and give these people a pat on the back for teaching the rest of us!

BuildFree_Blog_banner

Comments

  • Pingback: Articles for 2014-apr-15 | Readings for a day()

  • “Let’s ask an important question: What’s the parent object when we invoke our getBackInTime function? The answer: the window.”

    This question, and the conclusion you come to, which is that the reason that `window` is the `this` binding for the `getBackInTime()` call has something to do with global variables… it’s an extremely common but incorrect explanation.

    Consider:

    (function(){
    var foo = {
    id: “foo”,
    bar: function(){ console.log(“id:” + this.id); }
    };

    foo.bar(); // id:foo

    var baz = foo.bar;

    baz(); // id:undefined
    })();

    In that code example, `baz()` is being invoked the same way `getBackInTime()` is being invoked, as a plain normal var reference, and the `window` object is the `this` in both cases. But clearly `baz` is not a global variable, nor is it of course a window property.

    This illustrates that the way `this` gets set to `window` (in both your example and mine) has nothing to do with global variables being properties of the window object (they are, but it’s an irrelevant fact here). Really, honestly, go check the spec.

    The rule that applies is the default binding rule when the call-site of the function looks like `fn()` and no other binding rule applies. It states that a default `this` is bound in that case. In non-strict mode, `this` will be the global object (`window` in browsers). In strict-mode, the default is `undefined`.

    If you’re interested in reading more, I’ve written a lot more about this stuff in my “this & Object Prototypes” book here: https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/README.md

  • @getify:disqus thanks so much for the response and for the example, Kyle! I’d like to clarify that I didn’t come to the conclusion window was the `this` context because it was the global object, nor because the `getBackInTime` function was a global var, but because window is the parent object of the function being invoked when you invoke `getBackInTime` in this instance. At the point which getBackInTime is created, the variable environment is the window, which is why it lands there as a global. The window is the ‘parent’ object when it’s invoked, and thus the `thisArg` passed under the hood will be the window. FWIW – I’ve always understood this explanation (“the parent object (caller) of a function determining the context (assuming no hijacking of `this` by apply/call, etc”) as a simplified way of explaining the typical (non-strict) behavior explained in http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3. (Forgive me, I know you know this, but explaining not only for clarity, but for any others reading our conversation and learning from it.)

    I opted to discuss this scenario with a global var because it is by far the most common situation I run into when reviewing code. I hope to cover the context issue in more depth in the future – and your example of how the thisArg can be the global when we’re *not* dealing with a global var is a great example of the more in-depth “context” knowledge that I want to help other new JS devs learn as well.

    Also – I’m glad you brought up the `strict` keyword, since I really should have covered that, too. It’s difficult to know when to draw the line and keep the content length readable, though! 🙂

    • Appreciate your response. Not to be too pedantic or nitpicky, but I think something was lost in communication. Trying to clarify.

      > nor because the `getBackInTime` function was a global var, but because window is the parent object of the function being invoked

      IIUC these two statements are equivalent. a function being referenced by a global var means that var is also a property of the global object, so when you invoke the function via that global var, you’re invoking the function via the global … which is the same observation as saying this function’s “parent object” is the global (window) object. Right?

      Am I missing something in your distinction that makes them not equivalent? Moreover, to quote you again (more fully) from the original article:

      > How do I know this? Well, unless I’ve wrapped the getBackInTime in a different scope [..], then any vars I declare get attached to the window. [..] So, getBackInTime‘s this context is the window

      It seems to me like you’re claiming the reason `getBackInTime` has a `this` value of `window` is because `getBackInTime` is a global variable. Is that a correct interpretation of your claim?

      If that *is* your claim, then I refer back to my original comment, which is that I believe this to be an inaccurate assertion of the *reason* for `this` being `window`. In my original comment, I showed another case `baz` where there’s a plain variable referencing a function, just like your `getBackInTime` variable is, and in both cases those function invocations result in `this` being `window`.

      If your claim is to be believed (as I understand it), then these two bindings must come about from two different rules, because `baz` in my example is clearly not a global variable, nor a global property, so the function it references clearly cannot have the window object as its “parent object”.

      My assertion is that both these examples result in a `this` of `window` from the same rule, and that rule doesn’t concern itself in any way with “the parent object” or whether something is in a global variable. The rule I’m asserting that’s in play for both examples is what I call the “default binding” rule, as I explained in my previous comment, and won’t repeat. 🙂

      Does that make it any clearer what my question/concern is?

      • It’s quite possible I haven’t had *enough* black tea today, and thus my explanatory skills are failing me. 🙂 It’s also certainly possible (more so) that my understanding needs to improve here.

        Let me quote Resig from the “Secrets of the JavaScript Ninja” book: “When we invoke the function as the method of an object, that object becomes the function context and is available within the function via the this parameter….Contrast this with invocation ‘as a function’, in which the function is defined on the window and called without the need to use a reference to window. Except for being able to leave off the implicit window reference, it’s the same thing. The function ‘belongs’ to window, and window is set as the function context, in the same way that object o is the function context in the above example [that example shows method invocation on an object].”

        This is the fun part – and perhaps where my understanding could be incorrect: In my example, the getBackInTime function truly exists on the window and when invoked, the window is the caller, and thus the context. In your example, the baz fn doesn’t exist on window of course, but in the scope of the “call object” (what the spec calls a NewDeclarativeEnvironment) created by your IIFE. If you were to console.log(this) inside your IIFE, you would of course see window logged, but the variable env is different, hence why baz doesn’t exist on window.

        The spec lays it out the algo that determines context like this:

        1.) If the function code is strict code, set the ThisBinding to thisArg.
        2.) Else if thisArg is null or undefined, set the ThisBinding to the global object.
        3.) Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
        4.) Else set the ThisBinding to thisArg.

        So – my question is this: when you’re in the *global scope* calling getBackInTime – is it technically two different invocations to call window.getBackInTime() vs getBackInTime()? Resig’s explanation, to me at least, makes it sounds like they are the same. Does the former follow the branch leading to #4 above, and the latter land at #2? (FWIW I understand your example and would expect the same context as what you’ve explained. I’m interested in dissecting the question of how the two diff invocations in global scope would be addressed in the spec’s context-determining-algo.)

        • You asked for a complete answer, here it is. It’s very long, so brace yourself. 🙂

          —————

          Repeating from Resig’s book: “Contrast this with invocation ‘as a function’, in which the function is defined on the window and called without the need to use a reference to window. Except for being able to leave off the implicit window reference, it’s the same thing. The function ‘belongs’ to window, and window is set as the function context, in the same way that object o is the function context in the above example [that example shows method invocation on an object].”

          Respectfully speaking, I disagree with John regarding this assertion. And while I can’t say I’m 100% unequivocally positive, I believe I can construct my reasoning from the spec (it’s far more complicated than just the 1,2,3,4 list you showed, unfortunately) to “prove” my assertions, which I will do below.

          > So – my question is this: when you’re in the *global scope* calling getBackInTime – is it technically two different invocations to call window.getBackInTime() vs getBackInTime()?

          Yes, these two different call-sites are distinctly different, and end up invoking a different mechanism in the spec for getting `this` bound. The fact that getBackInTime is a property of window is **entirely inconsequential** to the `this` binding, contrary to what Resig claims.

          To quote myself from my book (https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#determining-this ), here’s the 4 `this` binding rules as I understand (and teach) them, in order of precedence:

          1. Is the function called with new (new binding)? If so, this is the newly constructed object.
          – var bar = new foo()
          2. Is the function called with call or apply (explicit binding), even hidden inside a bind hard binding? If so, this is the explicitly specified object.
          – var bar = foo.call( obj2 )
          3. Is the function called with a context (implicit binding), otherwise known as an owning or containing object? If so, this is that context object.
          – var bar = obj1.foo()
          4. Otherwise, default the this (default binding). If in strict mode, pick undefined, otherwise pick the global object.
          – var bar = foo()

          So, back to our discussion of `window.getBackInTime()`, that call-site would hit rule (3) with `window` being the `this`. By contrast, `getBackInTime()` would miss rules 1-3, and would thus hit rule (4), which in non-strict mode would still end up with `this` as `window`. Two different rules, same `this` binding.

          The spec doesn’t really give any clues that `this` binding is inherited from where a function is declared, or even from where it’s called. The spec defines `thisArg` rules in the various 4 different ways that a function can be called, which is roughly how I came up with that 4-point call-site check-list I quoted of my book. I didn’t get the order of precedence from the spec, per se, though I’m sure it’s there somewhere — I got order of precedence from testing the 4 rules against each other.

          Let me see if I can briefly cite the various parts of the spec to lay out the support for my 4-point list above.

          * http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3

          This is the list you originally cited. It basically says that a function will be called with a `thisArg`, and that’s what will be used for `this` in general. Note points 1 and 2 basically show the distinction I make in my “default binding rule” between strict mode and not. In strict mode, whatever `thisArg` is passed in, that’s used. In non-strict mode, if `thisArg` is null or undefined, `this` gets set to the global (window) object. Other than that, this list doesn’t give us much else to answer our questions. It tells us we need to figure out how `thisArg` gets set, and what it gets set to. So, we move on further in the spec.

          * http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.3
          Points 6 and 7 in that list lay out 3 different ways that `thisArg` can be set. Point 6 says, if the function call is an object property reference, then it calls GetBase(ref) which basically returns ref as the `this` for normal objects we deal with. See the next bullet point for more on object property reference. Point 6 says otherwise, get `thisArg` from the environment record using “ImplicitThisValue()”. See two bullet points down for how that works. Finally, point 7 says if we have no reference at all (I believe these are like function expressions themselves, not references to them), then `this` is `undefined`.

          * http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
          This section in part defines how the IsPropertyReference(ref) works. It talks about looking at a reference for 3 parts, including a “base value” and a “reference name”. The “base value” AIUI would be the “foo” in “foo.bar()”. In “bar()”, the “base value” would be the environment record (the scope) where the call is being made. See the next bullet point for “environment record” `this` bindings.

          * http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.1.1.6
          Tells us that environment records, via “ImplicitThisValue()” always have `undefined` as their `this`.

          OK, so far, we have explained my rules (3) and (4) in my above list, via these spec citations. What about rules (1) and (2)?

          We need to find out how `thisArg` gets set in those cases.

          * http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.3
          * http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.4
          * http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.5
          apply, call, and bind all accept an explicit `thisArg` parameter, so it’s obvious that whatever you set it to is what will get passed along. That’s easy.

          Finally, what about the `new` operator?

          * http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.2
          Step 8, tells us that the newly created object is the `this` binding for that function call.

          —————

          Put all these things together, and I’m 99.9% sure that my list above represents in a human-friendly way a faithful exposition of how `this` binding works for normal functions. It’s entirely based on the call-site (that is, what the call looks like). It has nothing to do with where functions are declared or called “from”, only “how” they are called.

          One last example:

          function foo() { console.log(“id:” + this.id); }
          var obj = { id: “obj” };
          var id = “global”;

          function baz() {
          var bar = foo;
          foo(); // id:global
          bar(); // id:global
          }

          baz.call(obj);

          In this example, the foo() call and the bar() call both happen inside a baz function whose own `this` is `obj`, not `window`. Moreover, `foo` belongs to `window`, but `bar` belongs inside the local scope of `baz()`, so they have different “ownership”. Do they behave differently? Nope.

          No matter all that, the only thing that matters is the two call-sites “foo()” and “bar()”, and that they both invoke the default rule, which gives us the `window` as `this` binding since we are in non-strict-mode.

          Hope that’s made some more things clear. 🙂

  • joanmi

    «You might already know that you can take the marty object’s timeTravel method and copy it to another object»

    Wrong!!

    This is a subtle but sometimes important misconception:

    In the previous code you DIDN’T copied anything. You fust referenced an object (a function in this case) so you aren’t calling any copy of the function but the function itself only from a different call-site context (which is what “this” belongs to).

    “Copying” a function (or any other object) is not imposible, but a really strange practice in javascript… Why to spend resources to store two copies of the same thing?

    …this is useful only when you need to mantain diferent property values (state) on each one. But javascript is optimized to nearly never need to do this. Hence the “this” call-site context and the scope context duality.

    • @joanmi:disqus – I understand it’s a reference to the same function – my wording was poor, so I will update that to be clear as to what I mean.

      • joanmi

        Thank’s.

        My wording is even poorer. And sometimes I write things like “you Fust referenced…” 😉

        But this is an often confusing concept for many potential readers. Now I think is more clear.

        Thank you again.

      • joanmi

        Thank’s.

        My wording is even poorer. And sometimes I write things like “you Fust referenced…” 😉

        But this is an often confusing concept for many potential readers. Now I think is more clear.

        Thank you again.

      • joanmi

        Thank’s.

        My wording is even poorer. And sometimes I write things like “you Fust referenced…” 😉

        But this is an often confusing concept for many potential readers. Now I think is more clear.

        Thank you again.

  • PurnaChand

    Awesome Article

  • Last one is a sweet trick! Thanks

  • Pingback: Best of JavaScript, HTML & CSS – Week of April 7, 2014 | Flippin' Awesome()

  • Pingback: Javascript | Annotary()

  • Thanks for taking the time to write this out Jim!

    • burkeholland

      That’s the most beautiful head-shot of you ever.

      • Haha, its from the day I got married, 7.5 years ago. I was surprised to see its what Disqus still was using, haha.

  • brianm101

    The == and === says everything about what is wrong with Javascript! It’s so frustrating when you see something that should have been safe and simple to use become dangerous and complicated to use.

    Sometimes this happens by accident, laziness, design or compromise by the standards committee for the language. Not just JavaScript of course c++ is rapidly being updated with unnecessary core features that makes it harder to learn, use and less portable.

    Wish language designers would learn the basic principles of KISS (Keep It Simple S….) but guess by making things complicated it’s a great meal ticket for trainers in their later years!

    • @brianm101:disqus I can understand the frustration – especially if you’ve been bitten by JavaScript’s two equality operators. I can’t speak to the origins of *why* `==` exists, though I’d imagine it may have been for convenience given the amount of string representations of numeric data that could occur when parsing values off of urls, out of cookies, etc. (just a guess on my part). Like many features in a language, I’d imagine the creator(s) can’t possibly imagine the ways things can be abused. (For example, I’ve seen some insane abuses of reflection and operator overloading in C#!) Even one of my favorite “study as I have time” languages, erlang, has it’s blemishes (try intense string manipulation in it…ouch!). One thing I’d say that JS has going for it is that, compared to other widely popular languages in use in the typical enterprise (Java, C#) the language surface area is much smaller….so, usually less quirks to learn to beware of, and more time to focus on mastering it. 🙂

      • brianm101

        🙂 Keeping a language surface area small is a worthy goal unfortunately that appears to be the opposite of what happens!

  • Very nicely written Jim,

    Thanks for sharing 🙂

  • Pingback: Seven JavaScript Quirks I Wish I’d Known ...()

  • Eric

    If you’re trying to determine the ‘type’ of a JavaScript object/primitive, you can also check it’s ‘constructor’ e.g

    “foo bar”.constructor === String (true)
    /foo|bar/.constructor === RegExp (true)
    [‘foo’, ‘bar’].constructor === Array (true)
    new Date(2014,4,1,0,70).constructor === Date (true)

    Unfortunately this does not work for object literal notation.

    {‘foo’: ‘bar’}.constructor is a syntax error, however once assigned to a variable, it works the same as the others:
    var a = {‘foo’: ‘bar’};
    a.constructor === Object (true)

    Not that the value returned by ‘.constructor’ is not a string but rather a reference to the constructor.

    Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor

    • Eric thanks for commenting – I’m glad you mentioned this. You’re right, it won’t work on straight object notation because .constructor has to be called on a valid JS expression, so you could do something like:

      ({ foo: ‘bar’ }).constructor === Object; // (true)

      MDN is a fantastic resource, too 😉

  • Abdella Ali

    Great read! The bind/apply/call stuff was particularly useful for me, I’m looking forward to reading more from you!

  • Pingback: Weekend reading list | Daniil's Blog()

  • Almog

    I enjoyed reading this post and learned quite a few things.

    I wanted to ask you: what you meant by “unless we specifically return something else” (from the constructor part comments)?
    If a constructor function Foo returns some value:
    > var Foo = function(){
    ……… this.name = “I’m foo, that’s what I am”
    ……… return “Oh, am I?”
    ……… }

    The value returned by `new Foo()` will be “I’m foo, that’s what I am” rather than the function return value.
    I always guessed that it’s `new` that does both the change in the value of `this` as well as returning the value referred by `this`.

  • Pingback: Shared links for the past months - João Almeida - Programmer and Techie()

  • Pingback: Best from the world of a web development ( 13-19 April 2014)()

  • Pingback: Voodoo, Responsive Tables, JavaScript Graphs | The Treehouse Show Episode 90 | Treehouse BlogTreehouse Blog()

  • Pingback: Voodoo, Responsive Tables, JavaScript Graphs | The Treehouse Show Episode 90 | JJ SERVER()

  • Pingback: Seven JavaScript Quirks I Wish I’d Known About | slashwhatever.com()

  • Pingback: Is JavaScript Broken?()

  • Thor

    Good article, but if I may I’d like to provide a correction for the last point:

    Why are we using the toString on Object.prototype? Because it’s possible for 3rd party libraries, as well as your own code, to override thetoString method with an instance method. By going to theObject.prototype, we can force the original toString behavior on an instance.

    This is simply not true. Not only can the prototype toString be overwritten, this would be the typical way of overwriting a function in a library as it’s the only way to apply the change to objects created later. Consider the following:


    > String.prototype.toString = function() { return 1; };
    [Function]
    > String.prototype.toString.call(['foo', 'bar']);
    1

    The only way I’m aware of to actually guarantee that you’re executing the original (browser built-in) function that I’m aware of is to actually create a new iframe and get the function from the document there. I’m not even sure if that works for everything.

    As far as I know, the real reason for referencing the prototype here is that you can’t reference toString like that without either using the prototype object or a String instance and there’s no need to make a String instance just to execute the function. If you attempt to do something like String.toString.call(…), you get an error: “TypeError: Function.prototype.toString is not generic”. You could however get the result you intended by simply executing “”.toString.call([1, 2]), but that’s less clear than String.prototype.toString.

  • Pingback: JavaScript Quirks - Dan Blair()