Objects and the Prototype Chain 7

JavaScript is a language of objects. Everything is an object, and even those things that aren’t objects are often automatically converted to objects when they need to be. So, learning how to work with objects is an important part of becoming a better JavaScript programmer.

If you’ve been writing JavaScript at all, then you’ve used objects. This includes using frameworks and libraries like Backbone or jQuery. These libraries often use objects for settings, for function arguments, and they are, in fact, objects themselves – because everything in JavaScript is (or can be treated as) an object.

So, let’s get started.

Creating Objects

Creating an object in JavaScript is really, really easy, thanks to a little something we call an object literal.

var obj = {};

That’s it. You now have an object. It doesn’t do anything. It doesn’t contain anything. But it demonstrates an interesting feature of JS. Objects are blank canvases. You can add anything you want to them, in the form of a name/value pair. There are a few different ways to do that:

// In the original literal
var obj = {
    a: 17,
    'b': 92
};

// Dot notation
obj.sum = function() {
    return this.a + this.b;
}

// Bracket notation
obj['product'] = function() {
    return this['a'] * this['b'];
}

Obviously, there are a couple things to note here. When setting a property in an object literal, you can use a quoted string, or you can leave the quotes off. Either way, it’s interpreted as a literal string. This can be useful if, for some reason, you’re adding a property name that contains non-word characters, or is a reserved word. Wrap it in quotes, and it’s all good.

Secondly, you can set and access properties on an already-existent object with either dot notation, or bracket (array) notation. It’s the same thing, but you have to use a quoted string (or something that will coerce to a quoted string) in bracket notation.

Easy enough. Let’s get to something a little less basic.

Inheritance

I’ve already mentioned JavaScript’s prototypal nature. Let’s explore what that means.

Every object has a prototype property (often named __proto__), the value of which is another object. When we try to access a property on an object, it first checks its own properties, and then it checks its prototype’s properties. This continues recursively until the property is found, or there are no more prototypes to check. This is referred to as the prototype chain, and it’s how JS implements inheritance. Object inherit from other objects – a very important and powerful concept.

If we take a look at our example object from above, we can see that even blank object literals end up with a prototype – the native Object – which contains functionality like hasOwnProperty, toString, and others.

Object
    __proto__: Object
        __defineGetter__: function __defineGetter__() { [native code] }
            __defineSetter__: function __defineSetter__() { [native code] }
            __lookupGetter__: function __lookupGetter__() { [native code] }
            __lookupSetter__: function __lookupSetter__() { [native code] }
            constructor: function Object() { [native code] }
            hasOwnProperty: function hasOwnProperty() { [native code] }
            isPrototypeOf: function isPrototypeOf() { [native code] }
            propertyIsEnumerable: function propertyIsEnumerable() { [native code] }
            toLocaleString: function toLocaleString() { [native code] }
            toString: function toString() { [native code] }
            valueOf: function valueOf() { [native code] }

“Great!” you say. “So I just set the __proto__ property to an object, and now I have an object that inherits from another object!”

Well, no. It is pretty much that easy, but most implementations don’t allow you to modify the __proto__ property directly. In fact, I’m pretty sure the name is only a defacto standard anyway, so it’s likely that it won’t work across implementations.

No. Instead, we use Object.create. Since it’s getting a little more complicated, I’ll switch up the example.

var point = {
        translate: function(x, y) {
            this.x += x;
            this.y += y;
        },
        moveTo: function(x, y) {
            this.x = x;
            this.y = y;
        }
    };

var inheritingPoint = Object.create(point);
inheritingPoint.x = 45;
inheritingPoint.y = 62;

inheritingPoint.translate(5, 6);
inheritingPoint.moveTo(100, 75);

Here we create an object with some properties – in this case, a couple functions. point is a usable object unto itself. If we were to give it an x and a y (either by setting them directly, or calling point.moveTo(x, y)), we could move and translate this point, and it would work just fine. But we want lots of points, and we want them to have the same functionality as point. So we Object.create(point). This creates another object with a prototype of point. We can then set an x and a y, and use it in exactly the same ways that we would use point.

When we call translate on inheritingPoint, it first looks at its own properties. Since it doesn’t find translate, it looks at its prototype. translate is found, and then called. Since there’s a search up the prototype chain, there is a little bit of a performance hit. At this level, it’s basically meaningless, but it’s something to be aware of when designing your object structures; don’t go too deep, or the performance will suffer.

In the prototype-based world, this default behavior is referred to as delegation – there are explicit pointers through the prototype chain. (This is in contrast with concatenation, which I won’t cover here.) What this means is if your prototype object (in this case, point) changes, then every inherited object essentially has its functionality changed as well. If we change the definition of point.translate, calling inheritingPoint.translate will use the new functionality, because it looks up the chain, and finds the new function.

So, we have lots of different functions defined on lots of different objects, all of which are inheriting from each other. But there’s this keyword that keeps popping up, and it doesn’t seem to have the same value all the time.

What’s the Deal With “this”?

this is a special keyword in JavaScript, and it’s sometimes a difficult and tricky one to grasp. But here’s the way I think about it:

this is the calling context of the function.

For instance, calling point.moveTo (from the example above) is pretty straightforward. this refers to point. It’s the object that called the function moveTo (or, to fit it into my pseudo-definition, point is the context from which moveTo was called).

Calling inheritingPoint.moveTo(42, 52), though it goes through the prototype chain, still considers inheritingPoint to be the calling context. So, when this.x is set to the argument x, inheritingPoint has its own property x set to whatever we passed in. Maybe a code sample will make it clearer:

var inheritingPoint = Object.create(point);
inheritingPoint.moveTo(100, 75);
inheritingPoint.hasOwnProperty(x); // true

Even though the function moveTo is defined in point, and not in inheritingPoint, this refers to inheritingPoint when inheritingPoint.moveTo is called. This is very important to the way our object structures work; if it didn’t happen this way, then objects would have trouble keeping their own identities. As mentioned before, the prototype would change, and the the functionality of everything further down the chain would be affected. So, it’s a good thing this looks at the calling object, rather than whichever object defined the function.

Polymorphism and Function.prototype.call

Polymorphism is one of those basic concepts in Object-Oriented Programming. It’s taught in every 101 class. In JavaScript, it’s pretty straightforward. Let’s create a more specialized point – maybe a point in 3-dimensional space.

var point = { translate: function(x, y) { this.x += x; this.y += y; }, moveTo: function(x, y) { this.x = x; this.y = y; } };
var point3d = Object.create(point);

point3d.translate = function(x, y, z)
{
    this.x += x;
    this.y += y;
    this.z += z;
}

point3d.moveTo = function(x, y, z)
{
    this.x = x;
    this.y = y;
    this.z = z;
}

var newPoint = Object.create(point3d);
newPoint.moveTo(42, 37, 96);

Easy enough! Now, when we call newPoint.moveTo, it looks at itself (and doesn’t find the function), then it looks at its prototype (point3d), finds the function there, and calls it. Since it’s already found the function, it doesn’t bother checking its prototype (point), and we don’t have to worry about the fact that we passed in 3 parameters, but there’s a version of moveTo that only has two.

If you’re like me, though, there’s something that bothers you about the above example. Oh yes. Duplicate code. I like my code to be as DRY as possible, and this doesn’t pass muster. Fortunately, there’s a solution.

In classical languages, an object might have a pointer to its parent class, and we could call parent.moveTo. In JavaScript, we might be tempted to do the same thing with __proto__. But as the big yellow warning at the top of the MDN page tells us, it’s non-standard. We can’t rely on a property named __proto__, and we can’t rely on its value being the object we want it to be.

In most cases, we’ll already have some sort of reference to the prototype of the object we’re using, and the functions are guaranteed to be public (more on that later), so why not just call them directly?

point3d.moveTo = function(x, y, z)
{
    point.moveTo(x, y);
    this.z = z;
}

var newPoint = Object.create(point3d);
newPoint.moveTo(42, 37, 96);

Look at the calling context. When we call point.moveTo, the calling context will not be newPoint – it will be point. This means x and y will be set on the prototype, and will never be accessed. We have to be able to call point.moveTo with a different context, and that’s where Function.prototype.call comes in.

point3d.translate = function(x, y, z)
{
    point.translate.call(this, x, y);
    this.z += z;
}

point3d.moveto = function(x, y, z)
{
    point.moveTo.call(this, x, y);
    this.z = z;
}

var newPoint = Object.create(point3d);
newPoint.moveTo(42, 37, 96);

Perfect! point.moveTo.call changes the context of moveTo to whatever we supply as the first argument – in this case, this (so, whatever the current calling context is – yes, it’s confusing). x, y, and z are all set correctly, on newPoint, rather than in the rest of the prototype chain. This means newPoint is its own object – there’s no chance that changes to a different object will affect the values stored there.

A Quick Note On Visibility

Everything is public. There are ways to emulate private variables using closures, and I will cover that in a later article. But for now, it’s best to get used to the idea of making all your properties public.

And There’s More

This article should give you a good base line for using objects and inheritance in JavaScript. But the method presented can be pretty verbose. For good, DRY code, you’ll probably want to take advantage of any one of several object oriented design patterns, like the Factory Pattern, the Initializer Pattern, or (maybe) the Constructor Pattern. I’m in the process of writing tutorials on each of these, and will be posting them to this blog as well as my own.

About Me

I wear several hats, and I do a lot of different things. By day, I’m a mild-mannered web developer for McKissock Education. By night, I’m CTO and Lead Developer of SlickText.com – Text Message Marketing service. I’m also a musician, songwriter, dancer, and pretty cool guy.

January 14th, 2013 by

7 thoughts on “Objects and the Prototype Chain

  1. Reply Brenton Jan 30, 2013 1:07 pm

    A couple typos:

    returh -> return
    ant -> want

  2. Reply The Sosana Apr 13, 2013 7:06 pm

    1+ on this one, great write up, keep them coming!! this is a great referral for OOP in javascript!!

  3. Reply Dori :)~ Jul 18, 2013 6:18 pm

    So I definitely was not educated on JS prior to reading this blog. However, I can actually say after reading most of it (gave up at “what’s the deal with ‘this’” bc my brain couldn’t absorb anymore) that I learned a little something! I swear I could hear your voice when I was reading along. :) Kudos to a well written tutorial that is apparently well respected among your peers. I want to also vouch for the part in your bio… You are a “pretty cool guy”.

  4. Reply Alex Jan 8, 2014 6:07 pm

    Great article!

    Seeking clarification in line 3 of code in section:
    What’s the Deal With “this”?

    1 var inheritingPoint = Object.create(point);
    2 inheritingPoint.moveTo(100, 75);
    3 inheritingPoint.hasOwnProperty(x); // true

    should that be:
    3 inheritingPoint.hasOwnProperty('x'); // true??

    Thank you.

  5. Reply was Jan 30, 2014 10:44 pm

    console.log(inheritingPoint.hasOwnProperty(x)); // trigger: ReferenceError: x is not defined, on firefox
    // but
    console.log(inheritingPoint.hasOwnProperty(‘x’)); // return true
    // thank you for the article..

Leave a Reply