【问题标题】:Javascript prototype property not working as expected with array and object fieldsJavascript 原型属性无法按预期使用数组和对象字段
【发布时间】:2012-01-04 00:44:01
【问题描述】:

我得到以下代码的意外结果:

var TestModel, u, u2;

function TestModel() {}
TestModel.prototype.a = null;
TestModel.prototype.b = [];

u = new TestModel();
u.a = 1;
u.b.push(1);

u2 = new TestModel();
u2.a = 2;
u2.b.push(2);

console.log(u.a, u.b);     // outputs: 1 [1,2]
console.log(u2.a, u2.b);   // outputs: 2 [1,2]

我发现 u.bu2.b 包含相同的值令人惊讶,尽管根据我设置原型的方式,TestModel 的每个实例都应该有自己的实例变量。所以这是我期待的输出:

console.log(u.a, u.b);     // expecting: 1 [1]
console.log(u2.a, u2.b);   // expecting: 2 [2]

如果我将b 设置为对象并在其上设置键而不是将其用作数组,则会发生同样的事情。我在这里不明白什么?

【问题讨论】:

    标签: javascript prototype-programming


    【解决方案1】:

    赋值值和引用它们是有区别的。

    u.a = 1;
    

    将在u 引用的对象上创建一个新的a 属性。在赋值之前,u.a 会引用 TestModel.prototype.a,但赋值新值实际上会在实际对象上创建一个新属性:

    分配后:

    另一方面,

    u.b.push(1);
    

    不会创建新属性。它将引用现有属性,即数组,即TestModel.prototype.b

    即使TestModel 的每个实例都应该根据我设置原型的方式有自己的实例变量

    所有实例都引用同一个原型,因此它们引用原型所具有的相同属性。你可以很容易地看到,因为TestMode.prototype === u.bTestMode.prototype === u2.bu.b === u2.b 都产生了true

    如果您也为 u.bu2.b 分配一个新值,它会起作用:

    u.b = [];
    

    这通常在构造函数中完成:

    function TestModel() {
        this.b = [];
    }
    

    【讨论】:

    • 非常感谢!我没有意识到这种微妙的差异。所以基本上我应该在构造函数中初始化所有“实例”变量,然后再在其他地方操作它们。
    • @hiddentao:没错。可以将原始类型分配给原型属性,作为默认值,但是如果对象和数组是“每个实例”,则应在构造函数中对其进行初始化。我通常仍然在原型上定义属性,但是用null 初始化它(就像你用TestModel.prototype.a 做的那样)。
    • @Felix,你用什么工具来获得 TestModel 中值的漂亮图表?
    • @AresAvatar:这只是Chrome's Developer Tools控制台的截图。
    【解决方案2】:

    原型属性与每个实例都有自己的变量完全相反,原型的意义在于所有实例自动共享相同的原型属性,因此不需要为每个实例重新定义函数。

    您希望每个实例都有自己的数组,如下所示:

    function TestModel() {
    this.a = null;
    this.b = [];
    }
    

    【讨论】:

      【解决方案3】:

      在这两种情况下,数组都是相同的数组,即您为原型设置的数组。这意味着两个.push 调用都作用于该数组,因此所有这些都是[1, 2]

      TestModel.prototype.b
      u.b
      u2.b
      

      它们都指向同一个属性。

      原型通常用于函数,以便所有实例共享相同的函数。如果您要修改原型属性,那么它们也将反映在所有实例中,在这种情况下这可能是不可取的。如果每个实例都应该有一个自定义数组,那么还要为每个实例声明一个自定义数组,而不是通过原型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-22
        • 1970-01-01
        • 2013-09-26
        • 2015-09-22
        • 2016-05-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多