Why is JavaScript prototyping?

2020-01-27 10:07发布

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');

标签: javascript
10条回答
不美不萌又怎样
2楼-- · 2020-01-27 10:59

The first method you give is faster, and it really begins to make sense when you write it in another order:

//Guitar function constructor
function Guitar(color, strings) {
  this.color = color;
  this.strings = strings;
}

Guitar.prototype.play = function (chord) {
  alert('Playing chord: ' + chord);
};

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

It is faster because Javascript does not need to execute the constructor to create the variables, it can just use the predefined variables of the prototype.

For a proof, see this speed test on a question that is much like this one.


And maybe this alternative version makes even more sense to you:

function Guitar(){
  // constructor
}

Guitar.prototype = {
  play: function(a){
    alert(a);
  },

  stop: function(){
    alert('stop it');
  }
};
查看更多
祖国的老花朵
3楼-- · 2020-01-27 10:59

Bro let me ask you one thing, what If you have Guitar, Casio, Violin and you want play same chords in each of these musical instrument.

So I guess why don't we keep one function play_chord separately and use this(play_chord) function with any of above instrument, instead using each function inside Guitar, casio or violin.

so finally whenever we need a function which could be part of other constructor then we should define that particular function inside prototype and use accordingly :)

查看更多
家丑人穷心不美
4楼-- · 2020-01-27 11:05

You already have a lot of good answers that is why I'm not going through all of your points.

Why declare an instance and then start adding methods later?

That is not correct. The prototype object exists independently of every instance. It is a property of the function object (the constructor function).
When you create a new instance it "inherits" all the properties from the prototype (in fact, it has a reference to it).

Actually it makes sense if you think about objects and references: It is better (memory-wise) to share one reference to an object than each instance having its own copy of an object (the object in this case would be the function play).

As to why it is prototype based: You could also ask why different language paradigms exist (functional, oo, declarative). There is no only one correct way to do something.

查看更多
再贱就再见
5楼-- · 2020-01-27 11:05

It is based on the Prototype creational design pattern. This Wikipedia link has a nice discussion.

http://en.wikipedia.org/wiki/Prototype_pattern

查看更多
登录 后发表回答