Friday, March 15, 2013

Understanding JavaScript Objects

Sometimes I think JavaScript is a very misunderstood language. I think this stems from the fact that a lot of people (myself included) started using JavaScript as a means to complete quick and dirty tasks in browsers. As the web underwent transformations (remember “Web 2.0″?), the demand for richer, more interactive, client-side scripting increased. As that demand increased, a lot of us continued using JavaScript without really understanding the language (again, I’m guilty). I’ve learned a lot since then, in large part from working with Joe Eames (@josepheames) on our Html5 player, which we set out to do in a much more methodical and maintainable way. I learned a lot about JavaScript objects during that project thanks to Joe’s expertise.

You might wonder, why do I need objects in JavaScript? Well, for the exact same reason you need them in other OO languages. They weren’t so necessary back in the day when JavaScript consisted primarily of small snippits or functions to handle simple things like onclick events. But, now that client-side JavaScript is evolving more and more into mini-applications (or not so mini in a lot of cases) it is becoming increasingly important that we structure that code in a well-encapsulated, cohesive way enabling us to write SOLID and maintainable JavaScript code. If you are writing more than just a few lines of JavaScript code and are not creating objects to encapsulate and separate responsibilities, understanding and using objects may help you write cleaner code.

So, what is a JavaScript object?
First of all it’s helpful to know that JavaScript objects can behave much like an associative array or a set of key/value pairs (like a dictionary, map, or hash in other languages). For each pair, the key is the property/method name and the value is the property value or method definition. So, it’s not surprising to see that, given an object called myCat, you can create properties on it in a way that looks very much like a dictionary or map, like this:
    myCat["name"] = "Fluffy";
    myCat["color"] = "White";
That syntax, by the way, is functionally equivalent to this syntax:
    myCat.name = "Fluffy";
    myCat.color = "White";

Why the difference?
Good question. Really, there is rarely a need to do it using the dictionary-type syntax; but that way does allow you to create property names that do not adhere to JavaScript identifier naming restrictions. For example, I could create a property like this myCat["fur color"] even though “fur color” has a space in it. I cannot do that in the second example. This may be helpful in rare occasions where you may be creating objects out of data you don’t control (like a json data source, for example). But keep in mind, if you create them like that, you must also consume them like that (var color = myCat["fur color"]); Generally it’s a good idea to steer away from non-identifier friendly property names. It’s also much nicer to be able to use the more simple syntax above.

Wait a second, where did myCat come from anyhow?
The object myCat would have had to have been created prior to executing the statements above or you’d get an error indicating that myCat is undefined (which happens to be true, since I’m currently catless). So lets look at some ways to do that. The easiest way to create an object is like this:
    var myCat = {};
That creates a new object with no properties or methods. Ok, so that’s not technically true. It would be more accurate to say it doesn’t have any of it’s own properties or methods. That object does have some inherited methods since almost all objects eventually inherit from Object in JavaScript and so they inherit its methods.

Lets look at some other ways to create an object, and this time I’ll create some properties while I’m at it:
Example A
    var myCat = {name: "Fluffy", color: "White"};
Example B
    var myCat = Object.create(new Object());
    myCat.name = "Fluffy";
    myCat.color = "White";
Example C
    function Cat(name, color) {
        this.name = name;
        this.color = color;
    }
    var myCat = new Cat("Fluffy", "White");
All of these create an object with two properties (name and color) with their values set to “White” and “Fluffy”, respectively. So, why would you ever use Examples B and C if you can do this just as easily with the syntax in Example A? Well, if all you need is a cat with a name and a color, then there is no reason to use the other examples. In fact, I almost never use the syntax in Example B. But what if you want to be able to create multiple instances of an object that have the same shape and have some common properties initialized to the same values? That is where Example C comes in. The Cat function can be used to create multiple instances of a cat.

Why is Cat a function, shouldn’t it be a class?
That is a question OO programmers learning JavaScript have been asking for ages. JavaScript doesn’t have actual classes (although like it or not, it is about to). Rather than provide classes, JavaScript uses constructor functions and uses the new keyword to create instances of the type defined by the constructor (and it’s prototype). The Cat function is a constructor function. A constructor function, combined with the new keyword on the last line of that example, work together to create new objects in much in the same way classes do in other OO languages.

Prototype, what is that? And I still don’t see why I’d use Example C!
In the above paragraph, I stated that JavaScript uses constructor functions with the new keyword to create objects defined by the constructor (and it’s prototype). But I have yet to show you how to use the prototype of a constructor function — and for that reason, our examples have not been very interesting (why use Example C when you could use Example A).

Let's expand Example C some:
    function Cat(name, color) {
        this.name = name;
        this.color = color;
    }

    Cat.prototype.age = 0;

    var myCat1 = new Cat("Fluffy", "White");
    var myCat2 = new Cat("Scratchy", "Black");
Now both cats 1 and 2 have different names and colors, but they are both age 0. Of course, I can now change each of their ages individually, but it’s nice that I can already count on the fact that that property is there and initialized to 0. That prototype is used to define members that will be inherited by objects created by the Cat constructor function. Don’t worry too much about the details of prototypes for the sake of this post. I will be submitting a follow-up post to this one that covers prototypes much more in depth.

One subtle thing to take note of where JavaScript varies from other OO languages is in the inheritance of property values. If I were to set Cat.prototype.age = 3 in the example above, every cat created from the Cat function would have a default age of 3. This is a departure from what you may be used to with traditional properties in other languages.

Let’s make this example even more interesting by exploring how we would add a method to the Cat function:
    function Cat(name, color) {
        this.name = name;
        this.color = color;
    }

    Cat.prototype.age = 0;
    Cat.prototype.speak = function() {
        alert('meow');
    }

    var myCat1 = new Cat("Fluffy", "White");
    var myCat2 = new Cat("Scratchy", "Black");
Now our cats are no longer mute. We can call myCat.speak(); and it will alert the value “meow”. This makes our Cat constructor function much more interesting. You can see how using this structure you could create constructor functions that have all the power of classes in other languages (plus a few more features, like inheriting values).

Now lets tie up a few loose ends…

So are objects really just a dictionary?
Remember earlier I said that objects were not much more than dictionaries or a map? Well, they are more than just that (see “More information on properties” below) but just to illustrate that they do have dictionary-like behavior, look at the following code (which will work with any of the myCat objects from examples A, B, and C):
    for(var prop in myCat) {
        console.log(myCat[prop]);
    }
This code would produce the following in the console log:
  Fluffy
  White
Notice that we could iterate over the properties in an object and access each of them, just like you could with a dictionary.

So all objects inherit from Object?
When I introduced examples A, B, and C above, I stated, that “almost all objects eventually inherit from Object.” Most likely all the objects you’ll create will inherit from Object (or some other object that inherits from Object). It is unusual to do otherwise, but just to illustrate that idea out here is how you could do that:

Using Example B
Instead of doing var myCat = Object.create(new Object());, you could simply do this: var myCat = Object.create(null);.

Using Example C
After defining the function in Example C, you could simply do the following to make it so that none of the instances created from the constructor function inherit from object: Cat.prototype.__proto__ = null;. The __proto__ property will be explained further in my post on prototypes.

More information on properties
There is another way to make properties, and again the need for this is rare, but it is good to understand that there is more to properties than meets the eye. When we created properties on objects in all of our examples above, it was actually doing much more than you would think. They are all equivalent to doing the following
    Object.defineProperty(myCat, 'color', {
      value: "White",
      writable: true,
      enumerable: true,
      configurable: true
    });
Notice that all properties have three properties themselves that affect the way they behave. The writable property is fairly self-explanatory; if a property is not writable, it’s value cannot be changed in your script after it is created. The enumerable property affects whether the property shows up when enumerating all the properties using for(var prop in myCat). And finally, the configurable property specifies whether the property’s writable and enumerable properties can be changed once the property has been created. Again, the need for these is much less common.

Conclusion
This should give you enough information to start creating your own constructor functions and objects and using working in a way much more familiar if you are used to doing OO programming. If you would like to read a little more about objects, this post (which I also linked above) has some great information. That post is about the new classes coming in the next version of JavaScript, but he had some great examples illustrating objects using the current JavaScript functionality too.

Friday, March 1, 2013

Understanding Javascript Prototypes

Never heard of prototypes in JavaScript? Heard of them but still don't quite understand them? Hopefully this post will help clear up some of the mystery around what JavaScript Prototypes are and why you should care. If you aren't familiar at all with prototypes, they come into play when you start working with objects and inheritance in JavaScript.

So, Why should I care?

It used to be that we could give very little thought to our JavaScript without much consequence since the amount of and complexity of our JavaScript used to be quite insignificant. But, as browser technology has advanced, we now find ourselves in a world that expects rich client-side behavior which requires much more complexity. As that complexity increases we can no longer eschew SOLID programming practices in our JavaScript. Understanding prototypes will clear up a few mysteries that occur as you begin to work with JavaScript in a more object-oriented way.

Prerequisite: Understanding JavaScript Objects

Before diving into this post on prototypes, it will be helpful if you have a basic understanding of what objects are in JavaScript, how they work, and how to create them. If you aren't familiar with these concepts, I highly recommend you read my post on Understanding JavaScript Objects.

In Understanding JavaScript Objects, I used the following examples of creating objects:

Example A
    var catA = {name: "Fluffy", color: "White", age: 0};
Example B
    var catB = Object.create(new Object());
    catB.name = "Fluffy";
    catB.color = "White";
    catB.age = 0;
Example C
    function Cat(name, color) {
      this.name = name;
      this.color = color;
    }
    Cat.prototype.age = 0;

    var catC = new Cat("Fluffy", "White");
In these examples, A and B produce identical results while example C produces a something different. Example B is not very commonly used since Example A is much less verbose and equally useful. While example A is very common and quite useful, it doesn't apply much to this blog post so I will be almost solely working with example C, which uses function Cat, for the remainder of this post.

Why is Cat a function instead of a class?

We know from Understanding JavaScript Objects that Cat is a constructor function. A constructor function really is no different than any other function, in fact the term "constructor function" is just a common nomenclature that suggests that the function will create properties on the object being created (represented by this). In other words, when we say var catC = new Cat("Fluffy", "White"), all that really is happening is the catC object is created and assigned to this for the duration of the call to the Cat function. Therefore, inside the function, this.name = name; is the same as saying catC.name = name. Hopefully, that helps to clarify that constructor functions are not doing anything magic, they are just normal functions that are creating properties on this -- even though we use them in a way that is similar to how classes work in other languages. In fact, using the new keyword, you can create an object out of any function (it just doesn't make sense with other functions).

Cat.prototype.age? What's that all about?

Ok, first of all, notice that Cat.prototype.age isn't really part of the Cat function. It's also helpful to realize when this code gets executed. Seeing the code all lumped together like that might fool you into thinking that Cat.prototype.age = 0; is being called when a new cat is created, which of course, on closer inspection is obviously not true. Usually this code (including the creation of the Cat function above it) is called when a web page is first loaded; thus making the Cat function available to be called. So think about what is happening there. The Cat function is being created and then the age property is being created (with a value of 0) on the Cat function's prototype.

Wait, functions have a prototype? What's a prototype?

Functions can be used to create class-like functionality in JavaScript; and all functions have a prototype property. That prototype property is somewhat like a class definition in other object-oriented langauge; but it is more than that. It is actually an instance of an object and every function in JavaScript has one whether you use it or not. Every function (constructor function or not) has a prototype object instance hanging off of it, interesting, huh?

So, let's talk about how this prototype object is actually used. When you create an object using the new keyword, it creates a new object, passes it in as this to the constructor function (letting that function do to it whatever it wants) and then, and this is the important part, it takes the object instance that is pointed to by that function's prototype property and assigns it as the prototype for that object.

So objects have a prototype property too?

Well, yes but you don't access it the same way and it isn't used for the same purpose as a function's prototype. And this is where a lot of confusion usually begins with prototypes (don't worry if your confusion began long before this, that's normal too). Objects do not have a prototype property, but they do have a prototype. Only, the word prototype means something different when talking about objects than it does when talking about functions. It would be nice if we had a different word, for now, let's call it proto (you'll understand why in a minute). So functions have prototypes and objects have protos. They are very similar, in fact, a function's prototype and an object's proto often (in fact, usually) point to the same object in memory.

An object's proto is the object from which it is inheriting properties. Notice I said it is the object from which it is inheriting properties, not the function or class, it really is an object instance in memory. This differs from a function's prototype which is used as the object to be assigned as the proto for new objects' created using this function as a constructor function. An object's proto can be retrieved by calling myObject.__proto__ in most browsers (thanks IE) and by calling Object.getPrototypeOf(myObject) in all browsers -- I'll use __proto__ going forward for simplicity.

So let's give an actual definition to each of these terms:
  • A function's prototype: A function's prototype is the object instance that will become the prototype for all objects created using this function as a constructor.
  • An object's prototype: An object prototype is the object instance from which the object is inherited.

Back to the examples

All that explanation can be confusing without showing some examples, so let's dive in. If you inspect the prototype of the cats in Examples A and B you get the following result:
    catA.__proto__;
    Object { }
But, if you inspect the cat in Example C you get this result:
    catC.__proto__;
    Cat {age: 0}
Side note: I am using chrome's developer console to execute these statements and I will be displaying the results shown by chrome in grey text as shown above.

Note that in examples A and B, they do have a prototype (__proto__) even though they were not created using a constructor function. Since we didn't specify a prototype for these, they have a prototype of Object. It is possible to create objects without a prototype using this syntax: var myObject = Object.create(null);, but that is very rare and I've never seen a use for it. So barring that example, I think it is safe to say that all objects eventually inherit from Object.

This is even true of catC; look what happens when we inspect catC further:
    catC.__proto__;
    Cat {age: 0}

    catC.__proto__.__proto__;
    Object { }

    catC.__proto__.__proto__.__proto__;
    null
Notice that catC has a prototype (__proto__) of Cat. Actually, to say it that way is not really accurate. Cat is a function, so it cannot be a prototype; remember in the definitions above that a prototype is not a function it is an object instance. This is important to remember when thinking about prototypes -- an object's prototype is not the function that created it but an instance of an object. Since this is important, let's explore it a bit further:
    Cat;
    function Cat(name, color) {
      this.name = name;
      this.color = color;
    }

    Cat.prototype;
    Cat {age: 0}

    catC;
    Cat {name: "Fluffy", color: "White", age: 0}
Look at the difference between Cat, Cat.prototype and catC. What this is showing is that Cat is a function but Cat.prototype and catC are objects. It further shows that Cat.prototype has an age property (set to 0) and catC has three properties -- including age...sort of (stay tuned). When you define a function, it creates more than just the function, it also creates a new object with that function as it's type and assigns that new object to the function's prototype property. When we first created the Cat function, before we executed the line Cat.prototype.age = 0;, if we would have inspected Cat's prototype it would have looked like this: Cat {}, an object with no properties, but of type Cat. It was only after we called Cat.prototype.age = 0; that it looked like this: Cat {age: 0}.

Inherited properties vs. native properties

In the above paragraph, I stated that catC had "three properties -- including age...sort of (stay tuned)"...thanks for sticking with me. Age really isn't a direct property of catC. You can see this by executing these statements:
    catC.hasOwnProperty("name");
    true

    catC.hasOwnProperty("color");
    true

    catC.hasOwnProperty("age");
    false
This is because age, actually belongs to catC's prototype; and yet, if I execute the statement catC.age;, it does indeed return 0. What is actually happening here, is when we ask for catC.age, it checks to see if catC has a property named age, and if it does it returns it, if not, it asks catC's prototype if it has an age property. It continues doing this all the way up the prototype chain until it finds the matching property or finds an object with a null prototype and if it doesn't find the property in the prototype chain it will return undefined.

So that's what prototype chaining is?

Yep. You may have heard of prototype chaining before. It is really quite simple to understand now that you (hopefully) understand a little more about how prototypes work. A prototype chain is basically a linked-list of objects pointing backwards to the object from which each one inherits.

Changing an function's prototype

Remember that a function's prototype is just an object, so what would happen if we started changing the properties of a function's prototype after we created objects from it? Consider the following examples:
    function Cat(name, color) {
      this.name = name;
      this.color = color;
    }
    Cat.prototype.age = 3;

    var fluffy = new Cat("Fluffy", "White");
    var scratchy = new Cat("Scratchy", "Black");

    fluffy.age;
    3

    scratchy.age;
    3

    Cat.prototype.age = 4;

    fluffy.age;
    4

    scratchy.age;
    4
So, notice that changing the age of the Cat function's prototype property also changed the age of the cats that had inherited from it. This is because when the Cat function was created so was it's prototype object; and every object that inherited from it inherited this instance of the prototype object as their prototype. Consider the following example:
    function Cat(name, color) {
      this.name = name;
      this.color = color;
    }
    Cat.prototype.age = 3;

    var fluffy = new Cat("Fluffy", "White");
    var scratchy = new Cat("Scratchy", "Black");

    fluffy.age;
    3

    scratchy.age;
    3

    Cat.prototype = {age: 4};

    fluffy.age;
    3

    scratchy.age;
    3

    var muffin = new Cat("Muffin", "Brown");

    muffin.age;
    4
First, notice that I did not just change the value of the prototype.age property to 4, I actually changed the Cat function's prototype to point to a new object. So while Muffin inherited the new prototype object, Fluffy's and Scratchy's prototypes are still pointing to their original prototype object, which they originally inherited from the Cat function. This illustrates the point that a function's prototype property "is the object instance which will become the prototype (or __proto__) for objects created using this function as a constructor."

One more example to illustrate this point. What would happen if I changed the value of the age property of fluffy's prototype? Would this be different than simply changing fluffy's age? Yes, it would be different. Think about the examples above, and about how age is not actually a property on fluffy, it is a property of fluffy's prototype.

So, given this setup:
    function Cat(name, color) {
      this.name = name;
      this.color = color;
    }
    Cat.prototype.age = 3;

    var fluffy = new Cat("Fluffy", "White");
    var scratchy = new Cat("Scratchy", "Black");
Compare this example:
    fluffy.age = 4;

    fluffy.age;
    4

    scratchy.age;
    3
To this example:
    fluffy.__proto__.age = 4;

    fluffy.age;
    4

    scratchy.age;
    4
These produce different results because in the first example, we are just adding a new age property to the fluffy. So in the first example both fluffy and fluffy.__proto__ have age properties with the vales 4 and 3, respectively. When you ask for fluffy.age, it finds the property on the fluffy object so returns it immediately without ever looking up the prototype chain.

Whereas in the second example, fluffy still does not have an age property, but it's prototype (which is the same instance in memory as scratchy's prototype) now has a the new value 4 thus affecting both fluffy's and scratchy's ages.

Multiple Inheritance

I have to confess, this is not something I use often because I tend to prefer composition over inheritance; but that is not to say it is without a place. Say you want to create a constructor function that "inherits" from another constructor function, much like you would do in other languages when you create one class that inherits from another. Let's look at an example of how you may do this:
    function Animal(name) {
      this.name = name;
    }
    Animal.prototype.age=1;

    function Cat(name, color) {
      Animal.call(this, name);
      this.color = color;
    }
    Cat.prototype = new Animal(null);

    var catC = new Cat("Fluffy", "White");

    catC.name;
    Fluffy

    catC.color;
    White

    catC.age;
    1

    catC.hasOwnProperty("name");
    true

    catC.hasOwnProperty("color");
    true

    catC.hasOwnProperty("age");
    false
Notice that age is the only property that is not a direct property of catC. This is because when we called the Cat constructor function, it passed in our new object (catC/this) to the Animal function which created the name property on the object. The Cat function then also added the color property to catC/this. But the age property was added to the Animal function's prototype, it was never added directly to catC.

Inheriting Functions

In all the examples above, I used properties like name, color, and age to illustrate objects and inheritance. However, everything that I have done above with properties can be done with functions. If we were to create a speak() function on the Cat Function like this: Cat.prototype.speak = function() { alert('meow'); };, that function would be inherited by all objects that have Cat as their prototype, just like with the name, color and age properties.

Conclusion and Credit

If you are like me, it will take some experimenting for all this to really sink in. I'd recommend duplicating the above examples in a jsFiddle or in Chrome developer tools and messing around with them to see what you can do. I think I'm gaining a firm grasp on JavaScript prototypes, but I'm sure I have more to learn. If you find any flaws in my logic, feel free to comment and point them out. And lastly, I'd like to thank Angus Croll and Yehuda Katz for their insightful posts on prototypes. I recommend you also read their posts here and here for another point of view on prototypes. Somehow it helps to have prototypes explained a couple of times from different angles for it to really sink in.