Javascript Classes

I reviewed Javascript classes by reading a blog post by Pivotal Labs. In it, the author explains how Javascript works behind the scenes when a new keyword is used. The post is a nice bullet-point explanation, but based on one of the comments, it appears that one bullet point is incorrect (further explained in #2 below).

I also referred to this chapter of Eloquent Javascript. It provides a clear explanation of what happens when you instantiate a new object using the new keyword. I found something missing after reading through the relevant text, so I decided to take my own crack at explaining what happens.

“If you can’t explain something simply, you don’t understand it well enough.”

- Albert Einstein

Upon encountering following code block, Javascript does a few things:

1
2
3
function Car() { }; var ford = new Car();
  1. It initalizes a new javascript object (aka {}). At this point, assume nothing is in the object. Lets verify this with Firebug:

    1
    2
    3
    4
    5
    6
    typeof Car // "function" typeof ford // "object"
  2. In this step, the new object is internally identified with its constructor. Emphasis on internally because it appears that this can’t be done manually by the developer, at least with the same results.

    According to the Pivotal blog post, the constructor of object is now set to the constructor Car(). One of the comments suggests this isn’t correct, and provides code to demonstrate. Adapting his code to this example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Car.prototype.hasOwnProperty(constructor); // true ford.hasOwnProperty(constructor); // false ford.constructor // Car()

    What the above code demonstrates is that the ford object has a method called constructor, but this is not a local property. The Eloquent Javascript chapter describes property lookup in more detail, but here’s a quick recap: a Javascript object keeps a reference to its constructor function. This reference is stored under the object’s constructor attribute. When an attribute request is made on the object, the interpreter attempts to look up that attribute in the object itself. If it isn’t found there, the interpreter attempts to look up the attribute in the object’s prototype, stored in object.constructor.prototype. The lookup chain continues further than that if a property isn’t found there, but that’s as much as we need to know for this example.

    The Pivotal blog post and the Eloquent Javascript posting don’t cover this in the detail I’m looking for, so I’m going to refer to the ECMAScript specification in section 15.2.2.1. I’m grouping the following 3 steps from that section together under this bullet point:

    1
    2
    3
    4
    4. Set the [[Prototype]] internal property of obj to the standard built-in Object prototype object (15.2.4). 5. Set the [[Class]] internal property of obj to "Object". 6. Set the [[Extensible]] internal property of obj to true.

    All of the above operations are done by the Javascript interpreter and the developer can’t do them directly.

    The [[Extensible]] property of an obj indicates that the object can be modified. You can’t directly observe this property on Car or ford, but there are built-in Object methods to do this:

    1
    2
    3
    4
    5
    6
    Object.isExtensible(Car) // true Object.isExtensible(ford) //true

    The [[Class]] property is readable only with typeof obj, and has generally been useless to me in my Javascript development experience. Most variables I’m interested in are of ‘object’ or 'function’. If I were working with another language, I would expect this property to contain the most specific user-defined class that the object is an instance of.

  3. It calls the object constructor with this set to newly created object. In this case, our constructor does nothing so this is essentially a no-op. In the general case, the code would look something like this:

    1
    constructor.apply(newobj, arguments);