javascript - 如何使用 JavaScript 原型(prototype)在实例之间共享属性

标签 javascript inheritance instance-variables prototype-chain

我对原型(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/

相关文章:

javascript - jQuery 选择器不适用于动态创建的元素

c# - ProtoBuf 属性 ProtoMember 是否继承了 C# 中的标记值

java - 如何在 Java 中通过参数检索对象内的数据?

c++ - 同时具有模板和非模板构造函数的类

objective-c - 合成的实例变量是作为私有(private)的而不是 protected 生成的吗?

objective-c - @interface 括号内外声明的变量

javascript - 在 photoshop 中比较像素值

javascript - JavaScript 和 Python 之间的交互

javascript - 尝试编译此代码根本行不通。从react.js和vscode中获取解析错误

Java父类(super class)方法: keyword "this" vs "super"