在基本数据上使用原型

时间:2014-07-20 07:51:12

标签: javascript prototype

有两种方法可以使用基本数据定义构造函数:

var Person1 = function() {
    this.name = "Wayne";
};
var Person2 = function() {};
Person2.prototype.name = "Wayne";

这是什么区别?

1 个答案:

答案 0 :(得分:2)

  

这有什么区别?

使用字符串或其他原语时,没有巨大的区别,但是第一个每个实例都获得了自己的name属性价值"Wayne";第二个,原型上只有一个 name属性,它的值为"Wayne"

ASCII-art可以在这里提供帮助,假设我们有:

var p1 = new Person();
var p2 = new Person();
var p3 = new Person();

使用您的第一个代码,我们得到了这个:

+-----------------+      +-----------------+      +-----------------+
|       p1        |      |       p2        |      |       p3        |
+-----------------+      +-----------------+      +-----------------+
| __proto__       |---+  | __proto__       |---+  | __proto__       |---+
| name: "Wayne"   |   |  | name: "Wayne"   |   |  | name: "Wayne"   |   |
+-----------------+   |  +-----------------+   |  +-----------------+   |
                      |                        |                        |
                      |  +---------------------+                        |
                      |  |                                              |
                      |  +----------------------------------------------+
                      |  |  +------------------+
                      +--+->| Person.prototype |
                            +------------------+
                            |                  |
                            +------------------+

使用您的第二个代码,使用原型,我们得到了这个:

+-----------------+      +-----------------+      +-----------------+
|       p1        |      |       p2        |      |       p3        |
+-----------------+      +-----------------+      +-----------------+
| __proto__       |---+  | __proto__       |---+  | __proto__       |---+
+-----------------+   |  +-----------------+   |  +-----------------+   |
                      |                        |                        |
                      |  +---------------------+                        |
                      |  |                                              |
                      |  +----------------------------------------------+
                      |  |  +------------------+
                      +--+->| Person.prototype |
                            +------------------+
                            |  name: "Wayne"   |
                            +------------------+

但重要的是要注意,当你这样做时:

p1.name = "Greyson";

... 更改Person.prototype.name(正常情况下);它为p1提供了自己的 name属性,告诉我们:

+-----------------+      +-----------------+      +-----------------+
|       p1        |      |       p2        |      |       p3        |
+-----------------+      +-----------------+      +-----------------+
| __proto__       |---+  | __proto__       |---+  | __proto__       |---+
| name: "Greyson" |   |  +-----------------+   |  +-----------------+   |
+-----------------+   |                        |                        |
                      |                        |                        |
                      |  +---------------------+                        |
                      |  |                                              |
                      |  +----------------------------------------------+
                      |  |  +------------------+
                      +--+->| Person.prototype |
                            +------------------+
                            |  name: "Wayne"   |
                            +------------------+

这是一个不对称的过程:当你属性时,在正常情况下,它会在你正在使用的实际对象上创建或更新一个属性;但是当你从一个属性中读取时,它会首先查看该对象以查看它是否具有它,如果它没有,它会转到该对象的原型对象,然后转到那个对象的原型对象等。因此,当您稍后尝试使用name的值时:

console.log(p1.name);
console.log(p2.name);
console.log(p3.name);

... JavaScript引擎首先查看实例(p1p2p3)以查看它是否具有该属性并使用该属性的值(如果有) ;如果实例没有,引擎会查看原型,如果有,则使用该属性。


我在上面说“正常情况”因为属性可以有getter和setter,这可以改变它的工作方式。我不会在这里讨论它,只是标记它。