为什么我的基类的object属性与所有子类实例共享?

时间:2015-10-20 08:50:03

标签: javascript

我试图理解我在fiddle中重新创建的行为。

function BaseObject(){}
BaseObject.prototype.value = 1;
BaseObject.prototype.obj = {value:1};

BaseObject.prototype.log = function() {
    console.log(this.constructor.name + " - Value: " + this.value);
    console.log(this.constructor.name + " - ObjValue: " + this.obj.value);
};

BaseObject.prototype.add = function(i) {
    this.value += i;
    this.obj.value += i;
};

function Derivation1(){}    
Derivation1.prototype = Object.create(BaseObject.prototype);
Derivation1.prototype.constructor = Derivation1;

function Derivation2(){}
Derivation2.prototype = Object.create(BaseObject.prototype);
Derivation2.prototype.constructor = Derivation2;

var first = new Derivation1();
var second = new Derivation2();

first.log();
first.add(1);
first.log();
second.log();

输出是:

Derivation1 - Value: 1
Derivation1 - ObjValue: 1
Derivation1 - Value: 2 <-- as expected
Derivation1 - ObjValue: 2 <-- as expected
Derivation2 - Value: 1
Derivation2 - ObjValue: 2 <-- Why is this two too and not 1?

行为表明,对象成员由所有实例共享或以静态方式访问,而原始成员各自驻留在自己的实例中。

有人可以对此有所了解吗?

1 个答案:

答案 0 :(得分:0)

嗯,它相当简单,真的 - 原型并没有被深深复制。您的所有对象都具有相同的obj实例,因为您从不为每个对象创建新的obj

只需使用构造函数(或某些init函数,如果您愿意)可变属性。它会为您省去很多麻烦:

function BaseObject() {
  this.value = 1;
  this.obj = { value:1 };
}

BaseObject.prototype.log = function() {
  console.log(this.constructor.name + " - Value: " + this.value);
  console.log(this.constructor.name + " - ObjValue: " + this.obj.value);
};

BaseObject.prototype.add = function(i) {
  this.value += i;
  this.obj.value += i;
};

function Derivation1(){
  BaseObject.call(this);
}

Derivation1.prototype = Object.create(BaseObject.prototype);
Derivation1.prototype.constructor = Derivation1;

function Derivation2(){
  BaseObject.call(this);
}

Derivation2.prototype = Object.create(BaseObject.prototype);
Derivation2.prototype.constructor = Derivation2;

var first = new Derivation1();
var second = new Derivation2();
var third = new Derivation1();

first.log();
first.add(1);
first.log();
second.log();
third.log();

请注意添加的third实例 - 如果您将其添加到代码中,您将会看到它 共享相同的obj实例。实际上,您的obj是一个&#34;静态属性&#34; - 虽然它不是只读的,所以你可以在任何情况下替换它。

另一个重要的事情是你必须在派生的构造函数中手动调用父构造函数 - Object.create创建一个未初始化的对象。