确实,原型属性是所有实例共享的。问题是您永远不会更改原型属性。用一些额外的日志看看你的小提琴:
"use strict";
var ConstructorFunction = function () {};
ConstructorFunction.prototype = {
counter: 0,
count: function () {
return ++this.counter;
}
};
var a = new ConstructorFunction();
var b = new ConstructorFunction();
$("#output").append(a.hasOwnProperty("counter") + " "); //false
a.count();
$("#output").append(a.hasOwnProperty("counter") + " "); //true
如您所见,只要您调用++this.counter
,就会创建一个本地属性,该属性将从该属性开始使用。
我假设这就是发生的事情:
++this.counter
被解释为this.counter = this.counter + 1
。首先,计算等号的右部分,并且由于您的实例没有counter
属性,因此使用原型的 counter 属性。此属性的值将加到 1,然后分配给this.counter
,它现在创建一个本地属性,就像分配一个根本不存在的属性时一样,例如a.xy = 1
. xy
在这种情况下,将是实例的本地属性。
编辑
有两种解决方法仍然可以让您使用原型属性:
1)在方法内部显式设置原型属性count
:
ConstructorFunction.prototype.count = function() {
return ++this.constructor.prototype.counter;
};
2) 调用 count 方法apply
并将原型用作上下文:
a.count.apply(a.constructor.prototype);
但是,如果您prototype
按照自己的方式设置属性,这两种方法都会出现问题。
ConstructorFunction.prototype = {
//...
};
这会覆盖完整的原型对象,因此也会覆盖它的构造函数属性。构造函数属性现在将指向原型链中的下一个更高的对象,即Object
对象。要解决这个问题,您可以在分配原型对象后手动设置构造函数:
ConstructorFunction.prototype.constructor = ConstructorFunction;
或分别分配原型对象的每个属性:
ConstructorFunction.prototype.counter = 0;
ConstructorFunction.prototype.count = function () {
return ++this.counter;
};