javascript - 试图理解 JavaScript 中原型(prototype)的意义

标签 javascript oop class prototype

我意识到这个问题已经被问了数百次,但是,我似乎无法理解 JavaScript 中“为什么”原型(prototype)是正确的概念,而不是模仿类(是的,我知道 JavaScript 是一种基于原型(prototype)的语言- 我收集了那么多)。

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

这是我目前如何理解 JavaScript 原型(prototype)的示例脚本:

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

...我曾假设原型(prototype)可能意味着它共享同一个对象,而不是每次都创建一个新对象 - 然而,显然情况并非如此,因为 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();

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

...有什么帮助吗?

最佳答案

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

确实如此。构造函数创建的所有实例共享一个原型(prototype)对象。

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

对于某些类型(例如数字、 bool 值、空值、未定义或字符串),当您通过 this.color 更改原型(prototype)对象上存在的属性时,它将创建一个实例上的 color 属性。原型(prototype)不受影响,因此新实例将具有原型(prototype)中定义的默认颜色。

如果您更新了由原型(prototype)对象的属性引用的数组或对象的成员,则所有实例都会看到更改。

...Why is the latter code not recommended?

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


为了进一步扩展,我要指出的是,当您的函数通过使用 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();

关于javascript - 试图理解 JavaScript 中原型(prototype)的意义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4841175/

相关文章:

javascript - 在 iFrame 中注入(inject)蒙版的 SVG 在 Firefox 中损坏

javascript - JSON 语法错误...我没有看到它

unit-testing - 如何测试仅将调用委托(delegate)给 AR 实体的聚合根方法?

python - 将列转换为类对象

javascript - 如何在类中设置局部变量

javascript - 在平面列表中 react native 导航

Javascript - KineticJS 创建自己的类

c# - 集合属性应该是只读的——漏洞?

c# - 可以在 <T> 中传递父类(super class)的子类吗?

java - 试图理解从类图到对象图的转换过程