Trying to understand the point of prototypes in Ja

2019-01-31 12:03发布

问题:

I realize this has been asked hundreds of times, however, I can't seem to grasp the concept of "why" prototypes in JavaScript are proper, as apposed to imitating classes (yes, I know JavaScript is a prototypical based language - I've gathered that much).

Like many other people striving to make JavaScript an everyday language that I use, I'm use to the regular OOP class style, as I've played around in Java (and used classes in ActionScript as well as PHP). However, while I think I understand how prototypes work, I can't seem to understand why they're needed.

Here's my sample script of how I'm currently understanding prototypes in JavaScript:

var Apple = function() {
    // An apple?
};

Apple.prototype.color = "red";

Apple.prototype.changeColor = function(new_color) {
    this.color = new_color;
};
Apple.prototype.getColor = function() {
    alert('color: '+this.color);
};

var apple1 = new Apple();
var apple2 = new Apple();
apple2.changeColor("green");
apple1.getColor();
apple2.getColor();

...I had assumed that maybe the prototype meant that it shared the same object instead of just creating a new object each time - however, it obviously isn't the case since both apple1 and apple2 have different colors, still (after running said script).

Then I wrote it in what's more of a object-oriented script:

var Apple = function() {
    this.color = "red";

    this.changeColor = function(new_color) {
        this.color = new_color;
    };
    this.getColor = function() {
        alert('color: '+this.color);
    };
};

var apple1 = new Apple();
var apple2 = new Apple();
apple2.changeColor("green");
apple1.getColor();
apple2.getColor();

With the exact same results (as expected). ...Why is the latter code not recommended? I have no problem using prototypes (assuming I used them correctly), but I need to understand the concept of "why".

...Any help?

回答1:

...I had assumed that maybe the prototype meant that it shared the same object instead of just creating a new object each time...

It does. There's one prototype object that is shared among all instances created from the constructor.

...however, it obviously isn't the case since both apple1 and apple2 have different colors, still (after running said script).

For certain types (for example number, boolean, null, undefined, or string), when you change a property that exists on the prototype object via this.color for example, it will create a color property on the instance. The prototype remains unaffected so that new instances will have the default color defined in the prototype.

If you had updated a member of an Array or an Object that was referenced by a property of the prototype object, the change would be seen among all instances.

...Why is the latter code not recommended?

Because you're constructing new identical functions with the creation of each new instance instead of sharing one instance of the functions via the prototype object.


To expand a little more, I'd point out that when your function is called as a constructor by using the new keyword, this in the constructor is the new instance. So any property you add to this is being added to the instance.

var Apple = function() {
      // Here "this" is the object being constructed. As such, we're adding
      //   a property "rotten" to every instance created
    this.rotten = false;
};

   // adding a "color" property to the prototype object
Apple.prototype.color = "red";

   // set the property "color" on the instance to the value of "new_color"
Apple.prototype.changeColor = function(new_color) {
    this.color = new_color;
};
   // first check to see if this instance has its own "color" property. If so,
   //    use it. If not, look at the prototype object to see if it exists.
Apple.prototype.getColor = function() {
    alert('color: '+this.color);
};

// two new instances each have their own "rotten" property, and don't have a
//    "color" property. Both share the prototype object, so if "color" is 
//    requested, it will come from there
var apple1 = new Apple(); 
var apple2 = new Apple();

// This will add an "color" property to the "apple2" instance
apple2.changeColor("green");

// Doesn't have a "color" property, so it looks to the prototype object
apple1.getColor();

// Has a "color" property, so it uses that instead of the "color" on the prototype
apple2.getColor();


回答2:

prototype allows you to add methods and properties to a class and it will apply it not only to the class, but also any current object instances of that class.