-1

As far as I understand,Prototypal inheritance and closure are two incompatible ways for creating objects.

  • With prototypes, all the instances share the same function
  • With closures, each instance has its own function (with its specific closure)

By creating object using clojure, I am referring to the following pattern:

    function createPerson(p){
           return { 
               getName: function() { return p;} 
           };
    }

When in writing a Javascript application, prototype is a better choice than closure for creating objects? I am not looking for general explanations about the advantages of prototypal inheritance. Instead, I would like to see a real-life web development scenario where prototype inheritance is really useful.

The only useful case I can think about is for augmenting basic types.

viebel
  • 19,372
  • 10
  • 49
  • 83
  • 1
    Who told you that Prototypal inheritance and closure are two incompatible paradigms? – KooiInc Mar 12 '12 at 07:12
  • Prototypical inheritance and closures are completely different topics. There is no question of comparing them. Both of them are also powerful feature of JavaScript. – Sarfraz Mar 12 '12 at 07:14
  • @Sarfraz My question is: what kind of problems in javascript are better solved with prototypes? – viebel Mar 12 '12 at 07:19
  • @KooiInc They are incompatible because functions defined in the prototype chain cannot access the closure. – viebel Mar 12 '12 at 07:21
  • 1
    it's not a question of when or who is powerful, it's how you build your project and choosing which of the two (or both) are needed. http://stackoverflow.com/q/9270665/575527 there are pros and cons for each, mainly that prototypes doesn't use much memory, but properties are public. closures on the other hand are faster, emulate priacy but take up more memory. prototypes have inheritance, closures.. im not sure but so far i haven't seen one. – Joseph Mar 12 '12 at 07:21
  • @YehonathanSharvit don't need to. it was answered in that link. they are different, but usage depends on what you need. – Joseph Mar 12 '12 at 07:58
  • @KooiInc I have updated the question to make it clearer what I mean by incompatible. Please consider voting back up – viebel Mar 12 '12 at 08:24
  • @Sarfraz I would like to compare prototypes and closures for object creation. I have updated the question. Please consider voting back up. – viebel Mar 12 '12 at 08:25
  • @Yehonathan Sharvit: I didn't cast a downvote, just wondered about where you had found such information. – KooiInc Mar 12 '12 at 08:53

3 Answers3

3

The question asked in that one doesn't sounds to me correct. Closures and Prototype inheritance are two different aspect of the language, they're not incompatible. JS is a OOP language based on prototypes rather than classes. Closure is a way to keep alive a scope of a function beyond its execution. I don't see why they should be incompatible. To make an example, I could have something like that:

function MyButton(tag) {
   tag.addEventListener("click", this.onClick.bind(this), false);
}

MyButton.prototype = {
   constructor: MyButton,

   onClick : function(event){
       this.doSomething();
   },

   doSomething : function() {
       // do something
   }
}

function MySpecialButton(tag) {
    MyButton.call(this, tag);
}

MySpecialButton.prototype = Object.create(MyButton);

MySpecialButton.prototype.doSomething = function() {
    // do something else
}

Notice that with bind I create a closure, just in a more elegant way, where ES5 is supported. You can obtain the same result using a more explicit closure, if you want:

function MyButton(tag) {
   var myself = this;
   tag.addEventListener("click", function(event) { myself.onClick(event) }, false);
}

You use prototype inheritance to have, well, inheritance, and closure to keep the scope you want when you need it.

ZER0
  • 24,846
  • 5
  • 51
  • 54
  • Thanks for your answer. Actually I was referring to `closure` used for object creation. I modified the question to make it clearer. – viebel Mar 12 '12 at 07:51
1

In your new example you don't "create a person". Instead, you return a plain js object. Again, is not about closure versus protytpe, because I can also have:

 function createPerson(p){
       return { 
           name : p,
           getName: function() { return this.name } 
       };
}

That doesn't take advantages of a closure, but use the same approach to create an instance of an object. As you see, using closure again has nothing to do with object creation, can be used – or not – together, despite if you use prototype or not:

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

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

I generally avoid that, but you can have it. Also:

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

So, if your question is "why I should create an object in this way instead of a plain object" – that has nothing to do with closures – the answer is "because then you take advantage of the inheritance":

function Mutant(name) {
    Person.call(this, name);
}

Mutant.prototype = Object.create(Person.prototype);

var cyclops = new Mutant("Scott Summers");

alert(cyclops instanceof Person) // true

alert(cyclops instanceof Mutant) // true

alert(cyclops instanceof Object) // true
ZER0
  • 24,846
  • 5
  • 51
  • 54
  • You are right. My question is: why I should create an object in this way instead of a plain object? – viebel Mar 14 '12 at 13:57
  • because the inheritance. Because you have the prototype chains, so you can inherit the properties and the methods from other objects. If you don't care having different type of object, then you can just use Object with all property and methods you need. Actually, you can also take advantages of inheritance without using directly prototype and function for constructor, but just object, using `Object.create`. – ZER0 Mar 14 '12 at 14:02
1

Prototypical inheritance can be useful if you are creating millions of objects in memory and they all shared the same prototypical parent which has lots of methods. That means they can share the same parent and therefore consumes less memory in the browser.

Kernel James
  • 3,752
  • 25
  • 32