Prototypes in JavaScript

Prototypes in JavaScript

Tutorial Details
  • Applications Used: JavaScript
  • Difficulty: Intermediate
  • Completion Time: 30 Minutes

When you define a function within JavaScript, it comes with a few pre-defined properties; one of these is the illusive prototype. In this article, I’ll detail what it is, and why you should use it in your projects.


What is Prototype?

The prototype property is initially an empty object, and can have members added to it – as you would any other object.

var myObject = function(name){
    this.name = name;
    return this;
};

console.log(typeof myObject.prototype); // object

myObject.prototype.getName = function(){
    return this.name;
};

In the snippet above, we’ve created a function, but if we call myObject(), it will simply return the window object, because it was defined within the global scope. this will therefore return the global object, as it has not yet been instantiated (more on this later).

console.log(myObject() === window); // true

The Secret Link

Every object within JavaScript has a “secret” property.

Before we continue, I’d like to discuss the “secret” link that makes prototype work the way it does.

Every object within JavaScript has a “secret” property added to it when it is defined or instantiated, named __proto__; this is how the prototype chain is accessed. However, it is not a good idea to access __proto__ within your application, as it is not available in all browsers.

The __proto__ property shouldn’t be confused with an object’s prototype, as they are two separate properties; that said, they do go hand in hand. It’s important to make this distinction, as it can be quite confusing at first! What does this mean exactly? Let me explain. When we created the myObject function, we were defining an object of type Function.

console.log(typeof myObject); // function

For those unaware, Function is a predefined object in JavaScript, and, as a result, has its own properties (e.g. length and arguments) and methods (e.g. call and apply). And yes, it, too, has its own prototype object, as well as the secret __proto__ link. This means that, somewhere within the JavaScript engine, there is a bit of code that could be similar to the following:

Function.prototype = {
    arguments: null,
    length: 0,
    call: function(){
        // secret code
    },
    apply: function(){
        // secret code
    }
    ...
}

In truth, it probably wouldn’t be quite so simplistic; this is merely to illustrate how the prototype chain works.

So we have defined myObject as a function and given it one argument, name; but we never set any properties, such as length or methods, such as call. So why does the following work?

console.log(myObject.length); // 1 (being the amount of available arguments)

This is because, when we defined myObject, it created a __proto__ property and set its value to Function.prototype (illustrated in the code above). So, when we access myObject.length, it looks for a property of myObject called length and doesn’t find one; it then travels up the chain, via the __proto__ link, finds the property and returns it.

You might be wondering why length is set to 1 and not 0 – or any other number for that fact. This is because myObject is in fact an instance of Function.

console.log(myObject instanceof Function); // true
console.log(myObject === Function); // false

When an instance of an object is created, the __proto__ property is updated to point to the constructor’s prototype, which, in this case, is Function.

console.log(myObject.__proto__ === Function.prototype) // true

Additionally, when you create a new Function object, the native code inside the Function constructor will count the number of arguments and update this.length accordingly, which, in this case, is 1.

If, however, we create a new instance of myObject using the new keyword, __proto__ will point to myObject.prototype as myObject is the constructor of our new instance.

var myInstance = new myObject(“foo”);
console.log(myInstance.__proto__ === myObject.prototype); // true

In addition to having access to the native methods within the Function.prototype, such as call and apply, we now have access to myObject’s method, getName.

console.log(myInstance.getName()); // foo

var mySecondInstance = new myObject(“bar”);

console.log(mySecondInstance.getName()); // bar
console.log(myInstance.getName()); // foo

As you can imagine, this is quite handy, as it can be used to blueprint an object, and create as many instances as needed – which leads me onto the next topic!


Why is Using Prototype Better?

Say, for instance, that we are developing a canvas game and need several (possibly hundreds of) objects on the screen at once. Each object requires its own properties, such as x and y coordinates, width,height, and many others.

We might do it as follows:

var GameObject1 = {
    x: Math.floor((Math.random() * myCanvasWidth) + 1),
    y: Math.floor((Math.random() * myCanvasHeight) + 1),
    width: 10,
    height: 10,
    draw: function(){
        myCanvasContext.fillRect(this.x, this.y, this.width, this.height);
    }
   ...
};

var GameObject2 = {
    x: Math.floor((Math.random() * myCanvasWidth) + 1),
    y: Math.floor((Math.random() * myCanvasHeight) + 1),
    width: 10,
    height: 10,
    draw: function(){
        myCanvasContext.fillRect(this.x, this.y, this.width, this.height);
    }
    ...
};

… do this 98 more times …

What this will do is create all these objects within memory – all with separate definitions for methods, such as draw and whatever other methods may be required. This is certainly not ideal, as the game will bloat the browsers allocated JavaScript memory, and make it run very slowly… or even stop responding.

While this probably wouldn’t happen with only 100 objects, it still can serve to be quite a performance hit, as it will need to look up one hundred different objects, rather than just the single prototype object.


How to Use Prototype

To make the application run faster (and follow best practices), we can (re)define the prototype property of the GameObject; every instance of GameObject will then reference the methods within GameObject.prototype as if they were their own methods.

// define the GameObject constructor function
var GameObject = function(width, height) {
    this.x = Math.floor((Math.random() * myCanvasWidth) + 1);
    this.y = Math.floor((Math.random() * myCanvasHeight) + 1);
    this.width = width;
    this.height = height;
    return this;
};

// (re)define the GameObject prototype object
GameObject.prototype = {
    x: 0,
    y: 0,
    width: 5,
    width: 5,
    draw: function() {
        myCanvasContext.fillRect(this.x, this.y, this.width, this.height);
    }
};

We can then instantiate the GameObject 100 times.

var x = 100,
arrayOfGameObjects = [];

do {
    arrayOfGameObjects.push(new GameObject(10, 10));
} while(x--);

Now we have an array of 100 GameObjects, which all share the same prototype and definition of the draw method, which drastically saves memory within the application.

When we call the draw method, it will reference the exact same function.

var GameLoop = function() {
    for(gameObject in arrayOfGameObjects) {
        gameObject.draw();
    }
};

Prototype is a Live Object

An object’s prototype is a live object, so to speak. This simply means that, if, after we create all our GameObject instances, we decide that, instead of drawing a rectangle, we want to draw a circle, we can update our GameObject.prototype.draw method accordingly.

GameObject.prototype.draw = function() {
    myCanvasContext.arc(this.x, this.y, this.width, 0, Math.PI*2, true);
}

And now, all the previous instances of GameObject and any future instances will draw a circle.


Updating Native Objects Prototypes

Yes, this is possible. You may be familiar with JavaScript libraries, such as Prototype, which take advantage of this method.

Let’s use a simple example:

String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, ‘’);
};

We can now access this as a method of any string:

“ foo bar   “.trim(); // “foo bar”

There is a minor downside to this, however. For example, you may use this in your application; but a year or two down the road, a browser may implement an updated version of JavaScript that includes a native trim method within the String‘s prototype. This means that your definition of trim will override the native version! Yikes! To overcome this, we can add a simple check before defining the function.

if(!String.prototype.trim) {
    String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/g, ‘’);
    };
}

Now, if it exists, it will use the native version of the trim method.

As a rule of thumb, it’s generally considered a best practice to avoid extending native objects. But, as with anything, rules can be broken, if needed.


Conclusion

Hopefully, this article has shed some light on the backbone of JavaScript that is prototype. You should now be on your way to creating more efficient applications.

If you have any questions regarding prototype, let me know in the comments, and I’ll do my best to answer them.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.twitter.com/k3vk4 Kevin Katzke

    Thank you! Awesome article i was just looking for a good one about prototypes in JS!

  • Jesus Bejarano

    Waow even my grandmother can understand this, thanks i always love to learn the best pratice of any lenguage, very good explanation ;)

    • selva

      Your grandma beat me…

  • http://croftmedia.co.uk/ Greg Tyler

    To go a little bit further into how prototypes compare to other methods and properties, I’d strongly recommend this page. It’s my goto if I ever have any scoping issues.

    • Sergey

      Now it’s my goto as well, thanks for the link!

    • http://blog.sklambert.com/ Steven Lambert

      Thank you for this post. I’ve been spending most of the day looking for a good explanation on how prototypes worked, and this post was the first one that explained it well enough to understand.

      Thank you as well Greg Tyler for the link, it’s another great example on how to use objects and prototype.

  • http://twitter.com/garbaczd David Garbacz

    I got a little lost during the nuts and bolts of explaining prototype since I’m relatively newer to Javascript, but the practical application of it made perfect sense!

    Great article and really leading me into the depths of Javascript’s capabilities!

    • http://twitter.com/garbaczd David Garbacz

      Also just in time for the Prototypal Inheritance lesson of jQuery in 30 Days!

  • http://snowhit.com Mr.Pohoda

    Thank you for this great explanation. This way of learning from simple examples fits me the best.

  • captainbetty

    Thanks! Great article.

  • Raymond

    Thank you for this article. One newbie question. Will all of the instances of GameObject in the array have a value of 0 for x and y, or will they get the random values defined in the original GameObject.

    • http://www.wdonline.com/ Jeremy McPeak

      All the instances will have random values for x and y.

      It’s of my opinion that the prototype should be reserved only for values that do not change. As currently written, each GameObject object will have undefined for width and height if no arguments were passed to the constructor.

      Defining the x, y, width, and height properties on the GameObject.prototype gives each instance default values for those properties, but the constructor overrides the them by creating “own” properties (properties that are created directly on the object). So defining those properties on on GameObject.prototype is rather moot. In fact, doing so is a waste of CPU and memory usage, as the JavaScript engine has to create GameObject.prototype.x, GameObject.prototype.y, GameObject.prototype.width, and GameObject.prototype.height, as well as x, y, width, and height properties on the instance itself.

      If I were writing the GameObject data type, I would do so like this:

      var GameObject = function(width, height) {
          this.x = Math.floor((Math.random() * myCanvasWidth) + 1);
          this.y = Math.floor((Math.random() * myCanvasHeight) + 1);
          this.width = 5; // default
          this.height = 5; // default
      
          if (typeof width === "number") {
              this.width = width;
          }
      
          if (typeof height === "number") {
              this.height = height;
          }
      };
      
      GameObject.prototype = {
          draw: function() {
              myCanvasContext.fillRect(this.x, this.y, this.width, this.height);
          }
      };
      • Raymond

        Thank you, Jeremy. Your explanations really helped with my understanding. I’ve actually seen code like this in video game tutorials. Until now it has been difficult for me to understand how values were being assigned to different object properties.

  • http://creadevwebs.com Mike

    Thanks a lot for this article! Definitely shed some light on the subject!

  • http://blog.asmor.com Ian Toltz

    As far as I can tell, the two code snippets below are equivalent:

    ==Without prototype==

    function Example() {
    this.SampleMethod = function () { console.log(“Hello World”); }
    }
    var example = new Example();
    example.SampleMethod();

    ==With prototype==

    function Example() { }
    Example.prototype.SampleMethod = function () { console.log(“Hello World”); }
    var example = new Example();
    example.SampleMethod();

    =================

    I don’t see any reason to use one over the other, technically. As far as formatting goes, I prefer the top version (w/o prototype) as it ensures you’re keeping everything together. If you’re using prototype, then it’s possible you might have stuff defined all over the place. Well, of course, you would never do something awful like that, but what about the guy whose code you end up having to maintain?

    • http://www.wdonline.com/ Jeremy McPeak

      Technically, one uses more CPU and memory (the non-prototype approach), the other doesn’t (the prototype approach). Linguistically, the prototype approach is more correct, as it follows the design of the JavaScript language itself.

    • http://dataverse.me Jed

      What Jeremy said. It’s not a big deal if you’re instantiating Example infrequently and/or SampleMethod is short. But for frequent instantiation and/or longer methods it’s bad form and bad performance to redefine the method for every instantiation. Prototype also has the benefit of future alteration, updating all instantiated objects with one modification to the prototype.

    • Yair Yehuda

      There is another significant drawback for using the first method.
      Should Example ever be extended, say by SuperExample, there will no no way to access SampleMethod from the base class, something like the following (I used extend method from YAHOO):

      function Example() { }
      Example.prototype.SampleMethod = function () {
      console.log(“Hello World”);
      }

      function SuperExample() { }

      YAHOO.lang.extend(SuperExample, Example);

      SuperExample.prototype.SampleMethod = function () {
      SuperExample.superclass.SampleMethod.call(this);
      console.log(“Hello Universe”);
      }

      Reason : The extends method (for most implementations that I know) does the following:


      var F = function() {}, i;
      F.prototype=superc.prototype;
      subc.prototype=new F();
      subc.prototype.constructor=subc;
      subc.superclass=superc.prototype;
      if (superc.prototype.constructor == Object.prototype.constructor) {
      superc.prototype.constructor=superc;
      }

      Thus, every method defined in the constructor function itself using the ‘this’ keyword won’t make it to the prototype of its base classes and won’t be available to them.

  • http://www.wdonline.com/ Jeremy McPeak

    I don’t want to be “that guy,” but it’s what I do ;)

    By default, constructor functions return the newly created object when called in conjunction with the new operator. So, return this is unnecessary.

    • Leigh Kaszick

      Haha, thanks Jeremy. I must say I don’t think I’ve every actually returned this in a constructor before and am unsure as to why I did it there! Probably written one too many methods that allowed for chaining and did it out of habit :\

  • http://maikeldaloo.com Maikel D

    Great article. Thanks for sharing.
    I always wanted to know more about prototype in JS.

  • Gabriel

    Cool.

  • http://www.jesperhagstrom.nu Jesper Hagström

    Wow, this was an excellent article! Thanks!

    When mentioning the came example I came to think of an old RPG I made in javascript, sloppy as hell and running really slow! Tried the prototype approach just now, what a performance boost! Maybe I should continue develop it after all… :)

    Cheers

  • javier

    What’s the difference btw:

    var foo = function(name){
    this.name = name;
    this.hi = function(){
    return “Hello “+this.name;
    };
    };
    var fooobj = new foo(“javier”);
    console.log(fooobj.hi())

    and:

    var foo = function(name){
    this.name = name;
    };
    foo.prototype.hi = function(){
    return “Hello “+this.name;
    };
    var fooobj = new foo(“javier”);
    console.log(fooobj.hi());

    • http://quintonpike.com Quinton Pike

      The difference is the first one has access to private variables, and the second one does not. Also the second one is much more memory efficient if you are creating more than one object.

      var foo = function(){

      this.name = ‘Accessible outside of this object’;
      var secret = ‘Not accessible outside of this object’;

      this.hi = function(){
      // has access to this.name & secret..
      }

      }

      var foo = function(){
      this.name = ‘Accessible outside of this object’;
      var secret = ‘Not accessible outside of this object’;
      }
      foo.prototype.hi = function(){
      // has access to this.name, but does NOT have access to secret.
      }

      It really just depends on what you are doing, they both have +’s and -’s.

  • http://www.slacko.org Davide

    Thank you.
    You made simple to explain one of the most difficult features of the language.

  • http://ph-7.github.com Pierre

    Thanks for good JS article!

  • Jean-Philippe Martin

    About the performance issue, i did a little jsperf test case here :

    http://jsperf.com/method-definition-with-or-without-prototype

    I had only two browser here to test it with but for IE6, using prototype give a definitive benefit. In the case of Firefox 12, it gets a little slower.

    Feel free to update the test case if you want.

  • http://evan-borden.com Evan Borden

    Great article. This does a nice job of demystifying the prototype chain.

    I however would discourage the practice of touching native prototypes. My method implementation may be drastically or even just slightly different then a native implementation. Your method implementation avoids stepping on native methods by checking for their existence, but it does not avoid the probably case of your implementation differing from the native one.

    This is why libraries like underscore.js avoid touching native prototypes and why prototype.js is a library on its death bed.

  • Tom

    Thank you Jeremy. At first I didn’t understand what are you talking about but now “big fog” disapperead :D I finally understand why people do such a thing in other languages also. Thank you.

  • http://none Alex

    The post is great I have headaches but still cooping up to learn! thnks!

  • http://www.welld.ch Michele

    I don’t get this part:

    // (re)define the GameObject prototype object
    GameObject.prototype = {
    x: 0,
    y: 0,
    width: 5,
    width: 5,
    draw: function() {
    myCanvasContext.fillRect(this.x, this.y, this.width, this.height);
    }
    };

    why did you choose to redefine the whole prototype instead of adding the single function?

    // add draw to the GameObject prototype object
    GameObject.prototype.draw = function() {
    myCanvasContext.fillRect(this.x, this.y, this.width, this.height);
    }
    };

    What are the values used for? as default values in case they’re not passed to constructor?
    ah, the second width is supposed to be “height”, I guess!

    • http://www.wdonline.com/ Jeremy McPeak

      To emulate native objects, as their properties are typically defined on the prototype. For example, the String data type looks (somewhat) like this:

      function String(thing) {
          // do something with thing
          // initialize "own" properties
      }
      
      String.prototype = {
          constructor : String,
          length : 0,
          indexOf : function(search, startAt) {
      
          }
      };
      • Manaday Mavani

        Thanks Jeremy! Your answer cleared my doubt (the same Michele had..). Nice Post!

      • sergeylukin

        So does it mean that it’s considered a good practice to define all properties in constructor’s prototype property object even if they are defined in the constructor as properties of this? Is it done to make API of constructor be more clear and provide default values in case properties are not defined in the constructor or is there another reason?

  • dani

    Thx very nice and helpful tutorial

    Q: What about inheritance for the GameObject? Only the constructor need to be extend and the (re)define not..right? or both?

  • sobri

    there is big difference using prototype

    basically u use prototype on something that u want to be share among all instance of that particular object

    eg:

    function Enemy() {
    this.execute = function () { console.log(“Attack”); }
    }

    let say u have 2 instance of enemy

    enemy1 = new Enemy();
    enemy2 = new Enemy();

    ok let see what happening here, obviously every instance of enemy object have copy of execute().That is complete of waste cause basically execute(), perform same thing on different instance of enemy..That is why u want to use prototype.

    function Enemy(){}

    Enemy.prototype.execute(){..}

    enemy1 = new Enemy();
    enemy2 = new Enemy();


    enemy100 = new Enemy();

    now let say we have 100 instance of Enemy, only one copy of execute() is exist in memory..That is one huge performance gain

  • Yair Yehuda

    Great Article, you guy know how to explain this stuff.

  • http://www.facebook.com/ugurozpinar Uğur Özpınar

    great article

  • sergeylukin

    Great article! However following part of article is confusing (correct me if I misunderstood it):


    var myInstance = new myObject("foo");

    In addition to having access to the native methods within the Function.prototype, such as call and apply, we now have access to myObject’s method, getName.”

    But myInstance doesn’t have prototype chain access to methods within Function.prototype, doesn’t it? Instead it has access to myObject.prototype and Object.prototype only.

  • raziq

    i have a question ,

    when we create an object like this

    function Person(first,last){

    this.first = first;
    this.last = last;
    this.full = function (){ alert(this.first + ” ” + this.last); }
    }

    person = new Person(‘abdul’,'raziq’);

    could we also add to person’s prototype anything like this

    person.prototype = ‘some functions or anything ‘;

    or its not possible once we created the object ?

    and there is a __proto__ property on person object

    person.__proto__

    but when i access person.prototype property its undefined ?

  • http://www.wpguru.com.au/ Robin Thebs

    width is defined twice in line 14 under “How to use prototype”, one of the parameter must height isn’t it?
    But good article. Great help.

  • sameer

    var GameLoop = function() {
    for(gameObject in arrayOfGameObjects) {
    gameObject.draw(); —————————————//this line of code is Wrong !!!!!
    }
    };
    The last snippet of code on “How to use Prototype” is wrong it should be this;
    var GameLoop = function() {
    for(gameObject in arrayOfGameObjects) {
    arrayOfGameObjects[gameObject].draw(); //right one is this !!!!!
    }
    };

  • Kevin

    What is the difference between doing this:

    window.myobject0 = {};

    and
    window.myobject1 = function ();

    and
    window.myobject2 = new function();

    I am confused