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

hid*_*tao 9 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]
Run Code Online (Sandbox Code Playgroud)

我发现它令人惊讶u.b并且u2.b包含相同的值,即使每个实例都TestModel应该根据我设置原型的方式拥​​有自己的实例变量.所以这是我期待的输出:

console.log(u.a, u.b);     // expecting: 1 [1]
console.log(u2.a, u2.b);   // expecting: 2 [2]
Run Code Online (Sandbox Code Playgroud)

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

Fel*_*ing 13

分配值和引用它们之间存在差异.

u.a = 1;
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

作业完成后:

在此输入图像描述

另一方面,

u.b.push(1);
Run Code Online (Sandbox Code Playgroud)

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

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

所有实例都引用相同的原型,因此它们引用原型具有的相同属性.你可以很容易地看到,由于TestMode.prototype === u.b,TestMode.prototype === u2.bu.b === u2.b所有的产量true.

如果您分配一个新的价值,以及到它的工作u.b,并u2.b还有:

u.b = [];
Run Code Online (Sandbox Code Playgroud)

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

function TestModel() {
    this.b = [];
}
Run Code Online (Sandbox Code Playgroud)


pim*_*vdb 1

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

TestModel.prototype.b
u.b
u2.b
Run Code Online (Sandbox Code Playgroud)

它们都指的是同一个属性。

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