试图理解JavaScript中原型的重点

cli*_*ame 30 javascript oop prototype class

我已经意识到这已经被问了好几百次,但是,我似乎无法理解"为什么"JavaScript中的原型是正确的,因为它模仿了类(是的,我知道JavaScript是一种基于原型的语言 - 我'我收集了很多).

像许多其他人一样努力使JavaScript成为我使用的日常语言,我习惯于常规的OOP类风格,因为我在Java中玩过(并且在ActionScript和PHP中使用过类).然而,虽然我认为我理解原型是如何工作的,但我似乎无法理解为什么需要原型.

这是我目前在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();
Run Code Online (Sandbox Code Playgroud)

...我曾经假设原型可能意味着它共享同一个对象,而不是每次只创建一个新对象 - 但是,显然不是这样,因为apple1和apple2都有不同的颜色,仍然(运行后说)脚本).

然后我用更多面向对象的脚本编写了它:

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();
Run Code Online (Sandbox Code Playgroud)

具有完全相同的结果(如预期的那样)....为什么不推荐后一个代码?我使用原型没问题(假设我正确使用它们),但我需要理解"为什么"的概念.

......有什么帮助吗?

use*_*716 32

...我原以为可能原型意味着它共享同一个对象,而不是每次只创建一个新对象......

确实如此.在构造函数创建的所有实例之间共享一个原型对象.

...然而,显然情况并非如此,因为apple1和apple2都有不同的颜色,仍然(在运行所述脚本之后).

对于某些类型(例如number,boolean,null,undefined或string),当您通过this.color例如更改原型对象上存在的属性时,它将color在实例上创建一个属性.原型保持不受影响,以便新实例将具有原型中定义的默认颜色.

如果您更新了由原型对象的属性引用的Array或Object的成员,则将在所有实例中看到更改.

...为什么不推荐后一个代码?

因为您通过创建每个新实例来构建新的相同函数,而不是通过原型对象共享函数的一个实例.


为了进一步扩展,我要指出当使用new关键字将函数作为构造函数调用时,构造this函数中新实例.因此,您添加到的任何属性都将this添加到实例中.

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();
Run Code Online (Sandbox Code Playgroud)

  • @vishwanath:对不起,抱歉。原型对象当然是共享的。如果有人尝试访问实例上不存在的属性,则它将查看该属性是否存在于原型中。我对Java不太熟悉,但是在阅读了有关静态变量的内容之后,我会说它们肯定是不同的。相反,原型是javascript的继承机制,其中原型对象实际上可以是另一个类的实例,从而导致该实例的原型链,其原型,该实例的原型直到结束。 (2认同)

Cra*_*ent 6

prototype允许您向类添加方法和属性,它不仅将它应用于类,还将其应用于该类的任何当前对象实例.