3

I've been trying to understand the concept of prototypes in JS, but for some reason I'm finding it really baffling. Why and when would you use a prototype?

What's the difference between this (from this MDN example):

function Person(gender) {
  this.gender = gender;
}

Person.prototype.sayHello = function()
{
  alert ('hello');
};

And this:

function Person(gender) {
  this.gender = gender;

  this.sayHello = function() {
    alert('hello');
  };
}

I think I understand how to use them, but I don't know why I would use them. Maybe I'm missing something - scratch that - CLEARLY I'm missing something!

Can someone please explain the difference between those two examples and why I should use one over the other?

Thanks!

John Conde
  • 207,509
  • 96
  • 428
  • 469
Adam Plocher
  • 13,142
  • 5
  • 42
  • 74
  • 2
    never wrap your head around anything, it is dangerous – ajax333221 Apr 03 '13 at 20:44
  • Thanks everyone, your answers were extremely helpful. I can see the major benefits of prototypes now and will try to use them more often. I guess the main thing that was keeping me using the other method was just the appearance of the code - everything self-contained within the "class" just seems cleaner looking to me. – Adam Plocher Apr 03 '13 at 21:17
  • @ajax333221 I consider your advice invaluable, as well. No more wrapping my head around things. Thank you! – Adam Plocher Apr 03 '13 at 21:22

4 Answers4

1

When you create a new Person() with the prototype example, it will not load sayHello() into the memory with the person object.

Instead, it will add it to the object as soon as it is needed/called, and it is only loaded once when it is.

When working with a lot of objects, this could save a lot of memory for the user.

Rene Pot
  • 23,406
  • 6
  • 64
  • 89
  • 1
    I always thought that a more accurate way was that when using the prototype, the method is only in one location and is used from that memory location. When the method is added the other way, the same method is duplicated in memory whenever an instance is created with the constructor function. – MichD Apr 03 '13 at 20:45
  • 1
    that is what I'm trying to say ;) – Rene Pot Apr 03 '13 at 20:46
  • Ah, I thought it might be. I think the "only loaded once when it is" sort of implies that the method gets added to the `this` of the instance, when it really just points back to the method in the prototype. – MichD Apr 03 '13 at 20:47
1

classes and inheritance. instead of spending an hour or two explaining it myself I highly recommend going through this little tutorial. I skipped it ahead to the section on prototypes and it explains it very well in a fun way.

Decker W Brower
  • 931
  • 6
  • 16
1

Person is a constructor and it is executed every time a new instance is created. Constructors are just functions and functions are just objects in JavaScript. Functions can have properties f.a = 1, just like a basic object: o = {a: 1}.

When you add a function as a property of an object, it's called a method. So by defining the methods of Person in the constructor, they are redefined on ever instantiation. As pointed out already, this is extra work.

By defining the methods upfront using the prototype property of functions, the methods are defined only once.

An additional benefit of defining methods on the prototype is that they become static. Static methods do not require an instance object. For example, the array slice method can be invoked on an array instance: [1,2,3].slice(1). But if we don't have an array instance, we can still access and invoke the slice method from the Array object's prototype: Array.prototype.slice.call(arguments).

Edit: static methods are more commonly seen as Object.method, not necessarily properties of the prototype. It should be clarified that the instance method .slice() was being invoked statically.

Rick Viscomi
  • 6,242
  • 2
  • 31
  • 46
1

Prototype is important for inheritance. If you do not need inheritance, then there is really no difference. However, consider this:

function Person(gender) {
 this.gender = gender;

 this.sayHello = function() {
  alert('hello');
 };
}

function User(){

}

How can a User be a Person? There is really no easy way here. However, this is possible with prototype:

jsFiddle Demo

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

Person.prototype.sayHello = function() {
  alert(this.name);
 };

function User(name){
 this.constructor(name);
}

User.prototype = new Person();

var u = new User("joe");
u.sayHello();//alerts joe

Now, we can go even further, and override the functionality of saying hello for User when using prototype like this:

jsFiddle Demo

User.prototype.sayHello = function(){ 
 alert("Username: " + this.name);
}
Adam Plocher
  • 13,142
  • 5
  • 42
  • 74
Travis J
  • 77,009
  • 39
  • 185
  • 250
  • 1
    Thank you Travis (and everybody!) This was a very thorough and well written explanation. I made one small edit - you missed a line of code (`User.prototype = new Person();`) from your jsFiddle link. I think I'm finally starting to really get the point of using prototypes. Thanks again! – Adam Plocher Apr 03 '13 at 23:27