Skip to main content

Why is JavaScript prototyping?



That may strike you as a grammatically incorrect and possibly insane question, but here's what I mean: When trying to understand the concept of prototype in JavaScript, I came upon examples that were slightly more or less complicated versions of the following:







//Guitar function constructor

function Guitar(color, strings) {

this.color = color;

this.strings = strings;

}

//Create a new instance of a Guitar

var myGuitar = new Guitar('Black', ['D', 'A', 'D', 'F', 'A', 'E']);

//Adding a new method to Guitar via prototype

Guitar.prototype.play = function (chord) {

alert('Playing chord: ' + chord);

};

//Now make use of this new method in a pre-declared instance

myGuitar.play('D5');







So, on to my problem: Why the hell would you want to do this? Why would you not just put the play function in Guitar to begin with? Why declare an instance and then start adding methods later? The only reason I can see is if you wanted myGuitar to not have access to play when it is originally created, but I can come up with no example that elucidates a reason as to why you would want something like this.





It seems like it would make more sense to do this:







function Guitar(color, string) {

this.color = color;

this.strings = strings;

this.play = function (chord) {

alert('Playing chord: ' + chord);

};

}

var myGuitar = new Guitar('White', ['E', 'A', 'D', 'G', 'B', 'E']);

myGuitar.play('E7#9');







The real problem here is that the second example makes sense to me while the first example does not, whereas in reality, the first example is probably better for some reason(s). Unfortunately, every tutorial I have ever found just goes through the steps of using prototype but not why the prototype paradigm exists at all to begin with.





It seems that prototype allows you to do things that you would not otherwise be able to do, but I can come up with no good reasons as to why you would want to do them.





Edit: Some responses:





  • When I said "Why declare an instance and then start adding methods later?" I was more critiquing all of the examples I see that play out in the order of my first example. When this order is changed, as in Harmen's response below, it does make slightly more sense visually. However, this doesn't change the fact that, in the same vein as my first example, you can create an empty object function constructor, declare 100 instances of this object, and then only afterwards define what the original object actually is by giving it methods and properties via prototype . Perhaps this is generally done this way to hint at the Copy vs. Reference idea outlined below.



  • Based on several responses, here is my new understanding: If you add all of your properties and methods to the object function constructor, then create 100 instances of that object, you get 100 copies of all of the properties and methods. Instead, if you add all of your properties and methods to the prototype of the object function constructor, then create 100 instances of that object, you get 100 references to the single (1) copy of the object's properties and methods. This is obviously faster and more efficient and is why prototype is used (aside from altering things like String and Image , as mentioned below). So, why not do this:







(Bulleted lists break any code right after them, apparently, so I have to add a line of separate text here)







function Guitar(color, strings) {

this.prototype.color = color;

this.prototype.strings = strings;

this.prototype.play = function (chord) {

alert('Playing chord: ' + chord);

};

}

var myGuitar = new Guitar('Blue', ['D', 'A', 'D', 'G', 'B', 'E']);

myGuitar.play('Dm7');





Source: Tips4all

Comments

  1. So, on to my problem: Why the hell would you want to do this? Why would you not just put the play function in Guitar to begin with? Why declare an instance and then start adding methods later?


    Javascript is not a 'classical' inheritance language. It uses prototypal inheritance. Its just the way it is. That being the case, the proper way to create an method on a 'class' is to put the method on the prototype. Note that I put 'class' in quotes, since strictly speaking JS has no notion of 'class'. In JS, you work on objects, which are defined as functions.

    You can declare the method in the function that defines Guitar, however, when you do that, every new guitar gets its own copy of the play method. Putting it on the prototype is more efficient in the runtime environment when you start creating Guitars. Every instance shares the same play method, but the context/scope is set when invoked so it acts a proper instance method you are used to in your classical inheritance language.

    Note the difference. In the 'why not this way' example you posted, every time you create a new Guitar, you need to create a new play method that is the same as every other play method. If play is on the prototype, however, all Guitars borrow from the same prototype, so they all share the same code for play. Its the difference between x number of guitars, each with identical play code (so you have x copies of play) vs x number of guitars sharing the same play code (1 copy of play no matter how many Guitars). The trade off is of course that at runtime play needs to be associated with the object on which it is called for scoping, but javascript has methods that allow you to do that very efficiently and easily (namely the call and apply methods)

    Many javascript frameworks define their own utilities for creating 'classes'. Typically they allow you to write code like the example you said you would like to see. Behind the scenes, they are putting the functions on the prototype for you.



    EDIT -- in answer to your updated question, why can't one do

    function Guitar() {
    this.prototype.play = function()....
    }


    it has to do with how javascript creates objects with the 'new' keyword. See the second answer here -- basically when you create an instance, javascript creates the object and then assigns the prototype properties. So this.prototype.play doesn't really make sense; in fact, if you try it you get an error.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex