我对原型(prototype)继承的理解是每个对象都有一个原型(prototype)属性。如果对象上不存在属性,则检查其原型(prototype)对象,依此类推。
在此示例中,我的原型(prototype)对象是一个具有计数器属性的简单对象。
我期望每个实例共享相同的原型(prototype),但它们似乎会获得新的实例。这段代码的输出是 00,我期待的是 01。
我是否遗漏了一些明显的东西?
"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.count());
$("#output").append(b.count());
这是 jsfiddle:http://jsfiddle.net/hdA6G/5/
最佳答案
确实,原型(prototype)属性是所有实例共享的。问题是你永远不会改变原型(prototype)属性。看看你的fiddle还有一些额外的日志:
"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
属性,因此使用原型(prototype)的 counter 属性。该属性的值将添加到 1,然后分配给 this.counter
,现在它会创建一个本地属性,与分配尚未分配的属性时的方式相同。根本就在那里,就像a.xy = 1
。在这种情况下,xy
将是实例的本地属性。
编辑
有两种解决方法仍然可以让您使用原型(prototype)属性:
1) 在 count
方法中显式设置原型(prototype)属性:
ConstructorFunction.prototype.count = function() {
return ++this.constructor.prototype.counter;
};
2) 使用 apply
调用 count 方法并使用原型(prototype)作为上下文:
a.count.apply(a.constructor.prototype);
但是,如果您按照您的方式设置 prototype
属性,那么这两种方法都会出现问题。
ConstructorFunction.prototype = {
//...
};
这会覆盖完整的原型(prototype)对象,因此也会覆盖它的构造函数属性。构造函数属性现在将指向原型(prototype)链中的下一个更高的对象,即 Object
对象。要解决这个问题,您可以在分配原型(prototype)对象后手动设置构造函数:
ConstructorFunction.prototype.constructor = ConstructorFunction;
或者单独分配原型(prototype)对象的每个属性:
ConstructorFunction.prototype.counter = 0;
ConstructorFunction.prototype.count = function () {
return ++this.counter;
};
关于javascript - 如何使用 JavaScript 原型(prototype)在实例之间共享属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16911132/