Prototyping in JS. Whats the need?

Hi

can someone please explain me whats the need of prototyping in javascript?

What I mean to say is, when you add a method/property to an object using “Function.prototype” syntax, why cannot you directly add that method inside that object when creating it?

Consider the following example:

Instead of doing this:


myobj = function(fname){
 this.fname = fname;
};

myobj.prototype.age = function (age) {
   this.age = age;
};

var x = new myobj('joe');
alert(x.fname);
x.age = 32;
alert (x.age);

I can do this:


myobj = function(fname, age){
 this.fname = fname;
  this.age = age;
};



var x = new myobj('joe', 32);
alert(x.fname);
alert (x.age);

So what do we need prototype for?

Any explanations will be appreciated.

Thanks

I can’t profess to understand this well, but I recently found this video really enlightening on the subject of prototypes:

http://www.objectplayground.com/

It’s the only explanation of prototypes that I’ve really been able to grasp.

There are a couple of important differences when you add a method to an object’s prototype rather than directly to the object itself:

  • The method will be available to all objects which inherit from that prototype, even if the objects were created before you added the method to the prototype.
  • The objects will reference the method from the prototype rather than being created with their own copy, which is more efficient if you’re creating a lot of the same kind of object.

Edit: +1 to ralph.m’s link too - that page is a great help to getting your head around how prototypes work in JS, I had a couple of lightbulb moments while watching the screencast.

Hi

Mind explaining this with an example?

Thanks

No worries.

Here’s an example that illustrates the first point:

var Person = function(name, age) {
    this.name = name;
    this.age  = age;
};

Person.prototype.talk = function() {
    console.log("Hi, I'm "+this.name);
};

var pete = new Person('Pete', 32);

pete.talk(); // Hi, I'm Pete

Person.prototype.sleep = function() {
    console.log('Goodnight! zzzzZZZZ');
}

pete.sleep(); // Goodnight! zzzzZZZZ

You see that we can call pete.sleep() even though we only defined the method after pete had been created.

In regards to the second point, lets say that we’d done something like this:

var Person = function(name, age) {
    this.name = name;
    this.age  = age;

    this.talk = function() {
        console.log("Hi, I'm "+this.name);
    };

    this.sleep = function() {
        console.log('Goodnight! zzzzZZZZ');
    }
};

Because we’re creating the methods in the constructor function, each time we call new Person() a new object will be created with its own copy of these methods. If we were running an app that created a large number of Person objects, we’d be using up more memory with all that unnecessarily duplicated method code.

Edit: If you want to visualise the prototype example at objectplayground.com, you have to make a few small changes to get sensible output from it:

function Person(name, age) {
    this.name = name;
    this.age  = age;
};

Person.prototype.talk = function talk() {
    console.log("Hi, I'm "+this.name);
};

this.pete = new Person('Pete', 32);

Person.prototype.sleep = function sleep() {
    console.log('Goodnight! zzzzZZZZ');
}

Excellent explanation fretburner

Cheers!!!

2 more questions

  1. Whats the difference between the following two codes?

  2. What benefit do I get when I use the prototype property?


function displayInfo(fname){
  this.fname;
}

displayInfo.age = 25;

console.log(displayInfo.age);


function displayInfo(fname){
  this.fname = fname;
}

sam = new displayInfo('Sam');
displayInfo.prototype.age = null;
sam.age = 33;
console.log(sam.age);

Nothing really. Even though you initialise the property age on the prototype and set it to null, when you do sam.age = 33; you’re actually creating an age property directly on the object sam. Visualise this code over at the objectplayground site and you’ll see what I mean:

function displayInfo(fname){
  this.fname = fname;
}

this.sam = new displayInfo('Sam');
displayInfo.prototype.age = null;
this.sam.age = 33;

As I mentioned in my previous post methods set on the prototype are available to all objects that inherit from it, and the same goes for properties set on the prototype. Of course, if you change the value via one of your objects all the others will now access the changed value, which may or may not be useful depending on what you’re trying to achieve.

Properties don’t need to be assigned via the prototype as they are not executable functions, instead you should use getter and setter functions that attach to the prototype but are more descriptive as to what you’re currently doing with the person.

Visit the following demo, press F12, jump over to the console and you will see that only functions are inherited via the prototype http://jsfiddle.net/MS4j6/.

If you define properties via prototype then you provide two different ways for the object to get its value - via the prototype or via the property directly attached to the object.

For example:

var obj1, obj2;
baseObject = function(x) {
if (typeof x !== undefined) this.prop = x;
}
baseObject.prototype.prop = 'default';

obj1 = new baseObject();
obj2 = new baseObject('unique');
alert(obj1.prop); // will display 'default'
alert(obj2.prop); // will display 'unique'
delete obj2.prop;
alert(obj2.prop); // will display 'default'

The property attached directly to obj2 in the above example overrides the one attached to the prototype but if you delete the property then the prototype property then once more becomes accessible via the property name and so even though the property has been deleted it still has a value.