有两种方法可以使用基本数据定义构造函数:
var Person1 = function() {
this.name = "Wayne";
};
var Person2 = function() {};
Person2.prototype.name = "Wayne";
这是什么区别?
答案 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引擎首先查看实例(p1
,p2
或p3
)以查看它是否具有该属性并使用该属性的值(如果有) ;如果实例没有,引擎会查看原型,如果有,则使用该属性。
我在上面说“正常情况”因为属性可以有getter和setter,这可以改变它的工作方式。我不会在这里讨论它,只是标记它。