19

Whats the difference between defining the method "area" as a property of "this" instead of "prototype"?

//console.clear()

function Rectangle(w, h) 
{
    this.width = w;
    this.height = h;
    this.area = function( ) { return this.width * this.height; }
}


var r = new Rectangle(2, 3);
var a = r.area( );

//console.log(a)

function Square(s) 
{
    this.side= s;
}

Square.prototype.area = function(){return this.side * this.side; }

var r = new Square(2);
var a = r.area( );

//console.log(a)

In JavaScript - The definitive guide in the section Prototypes and Inheritance of Chapter 9 , part 1, the author says that defining the method "area" inside the prototype object is beneficial, but his explanation wasn't really understandable:

"..the area of every single Rectangle object always refers to the same function (someone might change it, of course, but you usually intend the methods of an object to be constant). It is inefficient to use regular properties for methods that are intended to be shared by all objects of the same class (that is, all objects created with the same constructor)."

I know this question almost looks like this one, but it is not.

Community
  • 1
  • 1
instantsetsuna
  • 9,183
  • 8
  • 25
  • 28

1 Answers1

29

Defining a function with whatever = function() { ... } tends to create what's called a "closure", where the function can access local variables of the function that defines it. When you say this.fn = function() { ... }, each object gets an instance of the function (and a new closure). This is often used to create "private" variables in Javascript, but comes with a cost: each function (in each object) is distinct, and takes up more memory.

When you say Rectangle.prototype.fn = function() { ... }, one instance of the function is shared by all Rectangles. This saves memory, and can minimize some memory leaks in browsers that handle closures badly. If you don't need "private" members, or other such access to the defining function's local variables, it's usually a better idea.

cHao
  • 84,970
  • 20
  • 145
  • 172
  • 3
    Technically speaking, function() {...} always creates a closure, regardless of what it is assigned to. Everything else looks great! – ide Dec 08 '10 at 11:16
  • @ide: Good point. Edited. :) – cHao Dec 08 '10 at 11:30
  • @ide: Thanks for the explanation guys! Also, can you tell me where I can learn more about this? – instantsetsuna Dec 09 '10 at 06:14
  • 1
    I'm struggling to understand prototype, and questions like this help. I kind of get why you'd add a method on the prototype property as opposed to "this," but why wouldn't you do the same thing with the height and width variables and put them on the prototype? – Gregir Mar 08 '12 at 20:12
  • 2
    @Gregir: Because whatever is on the prototype is shared by everything that inherits from that prototype. In the case of variables, you often don't want that -- you want each Rectangle to have its own height and width, for example. So you set them on the object itself in the `Rectangle` constructor. – cHao Mar 08 '12 at 20:37
  • @cHao Following your conversation, just to make it more clear, the object blue-print/definition and the object instance are generated at the same time in JS? Why no Class and Instance like in Java and C# languages? – Yair Nevet Feb 15 '13 at 22:49
  • @YairNevet: Because that's how they did things. :) In JS, the instance *is* the "blueprint". There are a bunch of benefits, particularly where it comes to RAD and prototyping and such, as there's not nearly as much B&D code to write. – cHao Feb 16 '13 at 00:30
  • @Chao Thanks, what B&D means? – Yair Nevet Feb 18 '13 at 13:47
  • @YairNevet: "Bondage and Discipline". :) Basically, restriction and rules and annoyance for their own sake. Boilerplate code is a common example, but any code you have to write just to shut the compiler up is B&D code too. – cHao Feb 18 '13 at 14:27