Javascript 变量的继承不';行不通

Javascript 变量的继承不';行不通,javascript,Javascript,如果我在Javascript中使用原型继承,这些方法在子类中可用,但来自父类的成员是共享的。为什么会这样 例如,我正在从我的存储扩展2个数据结构类 function Store() { this._store = []; this._index = -1; } Store.prototype.addData = function (val) { this._index++; this._store[this._index] = val; }; Store.pr

如果我在Javascript中使用原型继承,这些方法在子类中可用,但来自父类的成员是共享的。为什么会这样

例如,我正在从我的存储扩展2个数据结构类

function Store() {
    this._store = [];
    this._index = -1;
}

Store.prototype.addData = function (val) {
    this._index++;
    this._store[this._index] = val;
};

Store.prototype.toString = function() {
    return "Store: [" + this._store + "]";
};

// inherits from Store
function DS1() {
}

DS1.prototype = new Store();
DS1.prototype.constructor = DS1;
现在,如果我使用两个DS1实例,它们使用的是相同的存储数据。为什么呢

var ds1 = new DS1();
ds1.addData(2);
console.log(ds1.toString());  // Prints 2

var ds2 = new DS1();
ds2.addData(3);
console.log(ds2.toString()); // Prints 3

console.log(ds1.toString()); // Prints 3 and NOT 2.

这就是为什么要使用。问题是,只有当
存储
构造函数运行时,才会创建新的唯一
\u数据
数组。您的
Store
构造函数只在
DS1.prototype=newstore()中运行一次
这意味着所有
新DS1()
实例共享相同的
\u数据
数组

下面是一个改编自。假设每个
存储
都有一个伪唯一的、随机的
id
属性:

var Store = function() {
    // each Store instance has a random id
    this.id = Math.random();
}
Store.prototype.addData = function() { /* ... */ }
然后,您希望
DS1
Store
继承:

var DS1 = function() {
    this.something = 5;
}
DS1.prototype = new Store();  // this is bad

var ds1 = new DS1();
console.log(ds1.id);

var ds2 = new DS1();
console.log(ds2.id);  // same as ds1!
坏消息--
DS1
实例现在都共享相同的
id
DS1.prototype.id
DS1.prototype=newstore()行上设置一次,这就是所有
DS1
实例从中获取
id
的地方

相反,您希望在每次运行
DS1
构造函数代码时运行
Store
构造函数代码,而不是在设置
DS1
原型时仅运行一次:

var DS1 = function() {
    Store.call(this);  // set parent constructor properties on `this` new DS1 obj
    //...
}

// DS1 prototype inherits from Store prototype, not Store instance
DS1.prototype = Object.create(Store.prototype);

这就是为什么要使用。问题是,只有当
存储
构造函数运行时,才会创建新的唯一
\u数据
数组。您的
Store
构造函数只在
DS1.prototype=newstore()中运行一次
这意味着所有
新DS1()
实例共享相同的
\u数据
数组

下面是一个改编自。假设每个
存储
都有一个伪唯一的、随机的
id
属性:

var Store = function() {
    // each Store instance has a random id
    this.id = Math.random();
}
Store.prototype.addData = function() { /* ... */ }
然后,您希望
DS1
Store
继承:

var DS1 = function() {
    this.something = 5;
}
DS1.prototype = new Store();  // this is bad

var ds1 = new DS1();
console.log(ds1.id);

var ds2 = new DS1();
console.log(ds2.id);  // same as ds1!
坏消息--
DS1
实例现在都共享相同的
id
DS1.prototype.id
DS1.prototype=newstore()行上设置一次,这就是所有
DS1
实例从中获取
id
的地方

相反,您希望在每次运行
DS1
构造函数代码时运行
Store
构造函数代码,而不是在设置
DS1
原型时仅运行一次:

var DS1 = function() {
    Store.call(this);  // set parent constructor properties on `this` new DS1 obj
    //...
}

// DS1 prototype inherits from Store prototype, not Store instance
DS1.prototype = Object.create(Store.prototype);

添加
Store。将(this)
调用到您的
DS1
“类”。之后,您可以开始为构造函数中的
DS1
特定属性赋值。

添加
Store。将(this)
调用到
DS1
的“类”。之后,您可以开始在构造函数中为特定于DS1的属性赋值。

正如注释中所述,所有孩子都使用同一对象作为原型。这就是原型继承的工作原理

这种继承中的原型对象作为子对象的方法和变量的备用存储

当您从
d1
d2
调用/获取var时,会查看它们是否有
addData
。他们没有。然后js研究了uuu原型。嘿,
新店就在那里!它是否有一个
addData
?对叫它


重要的是,
newstore
只调用一次,因此创建的对象代表您父母的所有孩子。

正如评论中所说,所有孩子都使用相同的对象作为原型。这就是原型继承的工作原理

这种继承中的原型对象作为子对象的方法和变量的备用存储

当您从
d1
d2
调用/获取var时,会查看它们是否有
addData
。他们没有。然后js研究了uuu原型。嘿,
新店就在那里!它是否有一个
addData
?对叫它


重要的是,
newstore
只调用一次,因此创建的对象代表父对象的所有子对象。

这是因为在Javascript中,对象不是通过值复制的,而是通过引用复制的。
。现在,当子对象修改原型时,子对象(这里是ds1、ds2)和父对象的原型指向同一个对象,父母得到了改变,兄弟姐妹也得到了改变继承可以通过创建空函数F()来实现,将其原型设置为父构造函数的原型,如下所示

    function extend(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}

这样,您只需使用
extend(ds1,Store)
即可继承

这是因为在Javascript中,对象不是通过值复制的,而是通过引用复制的。
现在,子对象(这里是ds1、ds2)和父对象的原型指向同一个对象,当子对象修改原型时,父对象得到更改,同级对象也得到更改继承可以通过创建空函数F()来实现,将其原型设置为父构造函数的原型,如下所示

    function extend(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}

这样,您只需使用
extend(ds1,Store)
即可继承

DS1的所有实例都共享相同的数据,因为只有一个
DS1.prototype.\u store
,ever.No。2不同的数据结构。用Java术语来说,DS1和DS2都扩展了存储,我希望它们都有自己的存储阵列。@aspillers删除了导致混淆的DS2。所以我有两个DS1的实例。为什么它们共享相同的数据?不,因为
DS1
构造函数没有设置
\u存储
属性。只有
Store
构造函数可以这样做,您只能调用它一次。如果您想了解更多关于原型的工作原理和构造函数函数的作用,您可以在下面的回答中了解它:DS1的所有实例都共享相同的数据,因为只有一个
DS1.prototype.\u Store
,ever.No。2不同的数据结构。用Java术语来说,DS1和DS2都扩展了存储,我希望它们都有自己的存储阵列。@aspi