Object Oriented Javascript

Posted on in javascript, webdev

If you are reading this I’d like to assume you know what Javascript is and the fact that it’s object oriented, what not many people know though is how to do the most common object oriented “things” in Javascript, such as inheritance, private functions and such.

The fact that Javascript is prototype based and not class based is what makes it hard to get into for most programmers. If you come from Java, PHP, C#, C++, Python, Ruby or pretty much any language you’ll find objects in Javascript are a bit unique, and they certainly are but in a good way!

Prototypes

What are prototypes? The concept is quite simple: Whenever you ask an attribute to an object, it will look for that attribute in itself, and if it cannot find it, it will look for it in a special hidden attribute called prototype, it will return the attribute if it can find it in that object, or undefined if it’s not there.

The prototype attribute is just an object which can also have a prototype attribute. As you can see prototypes are recursive in nature, and whenever you look for an attribute in an object it will look for it in the whole prototype chain and only return undefined if it’s not present in any prototype object.

There is a catch though, even though every object has a prototype attribute, you can only access the prototype attribute of functions! So you cannot do {}.prototype but you can do Object.prototype! That’s because Object is actually a function, we’ll talk more about that in the following sections.

Constructor Functions

As you might know a constructor is a function which gets called every time a new object is created, it’s used to initialize the new object.

Because Javascript has no classes the new keyword works on functions not classes, inside this function you can use the this keyword and it will point to your new object, for example:

We can now create a person

The function Person is called a constructor function and it starts with a capital letter. It’s super important to start all your constructor functions with a capital letter, not only it’s a convention, but if you call that function without the new keyword you’ll get unexpected results! Inside the constructor function this now points to the Window global object, and doesn’t return anything unless you say so. This is one of the most criticized features of Javascript, the inconsistency of the this keyword.

If you start all your constructor functions with a capital letter you’ll know just by looking that it must be used with new. Another option is to avoid the usage of the new keyword whenever possible:

This function also returns a new object. Which way to program is up to you, normally constructor functions is the only use case when using new is good, Douglas Crockford talks a bit about this in this YUI blog post.

A little more about the new keyword

Feel free to skip this little section, but I’d like to talk a bit about this keyword.

The new keyword creates a new empty object with our constructor function in the hidden prototype attribute, it then executes our function and binds this to the newly created object, finally it returns that object or if there’s a return statement, the value of that statement. MDN explains these steps nicely as follows

  1. A new object is created, inheriting from foo.prototype.
  2. The constructor function foo is called with the specified arguments and this bound to the newly created object. new foo is equivalent to new foo(), i.e. if no argument list is specified, foo is called without arguments.
  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn’t explicitly return an object, the object created in step 1 is used instead. (Normally constructors don’t return a value, but they can choose to do so if they want to override the normal object creation process.)

If you are interested you should check out the full article on MDN.

Encapsulation

One of the things that object oriented code allows you to do is hide certain functionality from the consumer, meaning you are able to keep an internal state for your object which is not needed for the consumer to know, this is sometimes referred as “black box” or Encapsulation.

Encapsulation is good, and it’s easy to implement in Javascript! Let’s see how:

Here we have a constructor function which returns an object, so that’s what the new keyword will return. That object uses a variable from inside the constructor function’s scope, which cannot be accessed from outside our new object!

What we just did is called a closure and they are used quite a lot in Javascript, it might seem hard to understand and use but it’s really handy once you get used to them!

Inheritance

One of object oriented programming most important concepts is inheritance, meaning an object can inherit all the properties and methods from another parent object, and also add their own specific functionality on top.

It’s a bit tricky but we can do it in Javascript with no major hassle, the idea is to use the prototype attribute to hold our base (a.k.a parent) object, so we can easily override/overload them if needed.

Because we can access the prototype attribute when working with functions we simply create a constructor function and then add an object to it’s prototype.

Note though that we are manually calling the parent’s constructor, this is not the most efficient way to extend objects as it not only executes the code every time you want to create a child instance, it also consumes more memory. What if the constructor makes an AJAX call or loops though a huge data structure? To bypass this we can use Object.create, it’s available on most browsers (IE8+) and it creates a new object with the specified prototype object and properties. Our code now looks like this

That way we copy all of the parent’s attributes into Sword’s prototype, and we maintain a clean prototype chain. If you are worried about compatibility, here’s Douglas Crockford’s polyfill:

Creating methods

When we want to add methods to an object, we could just add them in the constructor as we did before, but this isn’t a good idea as each instance would have a different copy of all of the defined methods. This isn’t going to break your app but it’s highly inefficient as all functions are executed in each instance context anyways. Let’s see how to use the prototype attribute to define methods:

As you can see, using “the good way” you can shares the function definitions across instances, consuming considerably less resources the bigger your app gets.

The constructor attribute

Something I haven’t talked about yet is the use of the constructor attribute. Every default Javascript object has this property, and it holds a reference to the function which created the object. What is it used for? Tim Down‘s reply on StackOverflow sums it up pretty nicely:

The constructor property makes absolutely no practical difference to anything internally. It’s only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you’ll need to set the constructor property explicitly when you set up inheritance by assigning an object to a constructor function’s prototype property[…]

It’s a good practice to add this, even though it’s not commonly used. I didn’t add it before for the sake of simplicity, but you should always add it just to keep things clean. Using the previous example, we can make things right by adding that property after we set up our prototype:

Revamped inheritance

Now that we know about Object.create and how to share methods across instances let’s rewrite our little example:

Much better! Please note that usually you won’t need to manually call the “super” constructor, I wanted to make a not-so-trivial example.

Static vs Instance

In the example above, for each Sword object we created the prototype Weapon object was copied, meaning each sword had it’s own copy of Weapon — There’s one copy per instance.

Sometimes you want to make a static attribute, meaning it’s shared across all instances, this is useful for sharing methods and data instead of copying them over and over. To create static attributes we use the constructor function.

The new keyword only copies the prototype of the constructor function, if we add any regular property it won’t be there in the new object, but we can easily access it later on, as we see here

foo.attribute vs foo.prototype.attribute

This is tricky, what you should know is that everything inside foo.attribute will be static, you don’t need to instantiate the constructor function in order to access the values. On the other hand, foo.prototype.attribute only works when called from an instantiated object, and even though you can share some objects like methods (because Javascript copies them by reference) you should always define static attributes in the function itself.

Abstracting it up a bit

A lot of libraries already provide a bunch of helper methods to easily get away with this, abstracting quite a lot of complexity, for example, in CanJS you create a model constructor function as follows

Most libraries create an extend function in their objects which simplifies the inheritance process, this method normally either uses the prototype attribute or just overrides an object properties. For instance, take a look at this MDN article on Object.create and John Resig’s Simple Javascript Inheritance article.

There are a lot of abstractions, but knowing how to do them “by hand” is quite important to fully understand your code! There is no knowledge that is not power ;)

Conclusion

All in all OOP in Javascript is possible and not that hard to archieve, it surely is different though! What I love about Javascript is that it’s such a simple language, you can do OOP as well as functional programming, or even mix both! In Javascript, that’s up to you.

I hope you find it useful and I’d like to hear your suggestions, Cheers!

  • Theodore Schnepper

    I do agree with doing Object Oriented Programming style via Prototyping in javascript. However, based on what you’re doing, I’d like to caution you on a few things.

    Firstly, your Person Object will take up massive amounts of memory merely due to the attempt to use private variables, and methods that can retrieve them. The primary issue with what you’ve done, is that the methods for each instance will take up their own memory, instead of using a combined memory set. (This is one of the issues that makes truly private variables in javascript a seemingly bad idea).

    As an example, consider the following:

    var person1 = new Person( ‘foo’ );

    var person2 = new Person(‘bar’);

    person1.name === person2.name; // false

    They inhabit different memory space.

    To counter-act that, you could continue trying to manipulate what you have to make it more performant, but I’m afraid you’ll run into other issues. I’d recommend adopting the style of this._name within the constructor. I understand that anybody could still access it, if they’d like, but it is usually understood that this is intended to be private, and it’s probably one of the best things we can do until EMCAScript fully supports private variables.

    At that point you can just install the functions into the prototype itself:

    Person.prototype.name = function( name ) { …. }

    and then this happens:
    person1.name === person2.name; // true
    Secondly, I’d like to cation you from doing inheritance with the following line:

    Sword.prototype = new Weapon(‘Sword’);
    Sword.constructor = Sword;

    The reason for this, is that this explicitly invokes Weapon’s constructor, and you will end up with a great many instantiated classes in a reasonably big project. Especially if you would use a ‘super’ constructor within Sword’s constructor like so:

    Weapon.call( this, typeStr);

    Another thing to keep in mind, is if you use this constructor call type with your private variable implementation, and you don’t explicitly call the super constructor within it, you will end up with shared private variables across your objects. Using your example again:

    function TallPerson(){}
    TallPerson.prototype = new Person(‘tall’);
    TallPerson.prototype.constructor = TallPerson;
    var tallPerson1 = new TallPerson();
    var tallPerson2 = new TallPerson();

    tallPerson1.name() // “tall”
    tallPerson2.name() // “tall”
    tallPerson1.name(‘foo’);
    tallPerson2.name() // “foo”

    At this point, all of the constructors within the prototype chain will be called. Instead, I recommend doing the following:

    Sword.prototype = Object.create( Weapon.prototype );

    It constructs the chain with a minor instance that is lighter on memory as it has no concern over the private/local variables you are creating/binding within your Object.

    I hope this helps you, I’ve been there before, and these few insights helped me to better understand the true issue with ‘private’ variables within javascript.

    • gosukiwi

      If you are going to use private variables you should stick to just closures (without using new).


      var create = function (name) {
      var _name = name; // my private variable
      return {
      getName: function () { return _name; }
      }; // return new object
      };
      var a = create('a');
      var b = create('b');
      console.log(a.getName() === b.getName()); // false

      As for using Object.create, that’s the better choice as long as you are not worried about IE8, which you shouldn’t. I talk about it in the last section, although I’ll try to make my point more clear.

      Thanks for the constructive criticism though :)