Javascript原型属性与数组和对象字段无法正常工作

时间:2011-11-22 16:23:35

标签: javascript prototype-programming

我使用以下代码获得了意外结果:

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设置为对象并在其上设置键而不是将其用作数组,则会发生同样的事情。我在这里不理解什么?

3 个答案:

答案 0 :(得分:13)

分配值和引用值之间存在差异。

u.a = 1;

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

enter image description here

转让后:

enter image description here

另一方面,

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 = [];
}

答案 1 :(得分:3)

原型属性与每个具有自己变量的实例正好相反,原型点是所有实例都自动共享相同的原型属性,因此每个实例都不需要重新定义函数。

您希望每个实例都有这样的数组:

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

答案 2 :(得分:1)

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

TestModel.prototype.b
u.b
u2.b

他们都指的是同一财产。

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