变量的继承不起作用

时间:2014-06-21 07:19:26

标签: javascript

如果我在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;

现在,如果我使用2个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.

4 个答案:

答案 0 :(得分:2)

这是使用new is discouraged for use with prototype的原因之一。问题是,当您的_data构造函数运行时,只会创建一个新的唯一Store数组。您的Store构造函数仅在DS1.prototype = new Store();中运行一次。这意味着所有new DS1()个实例共享相同的_data数组。

这是一个改编自different answer of mine的相关示例。假设每个Store都有一个伪唯一的随机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个实例现在共享相同的idDS1.prototype.id会在DS1.prototype = new Store();行上设置DS1,并且所有id个实例都会从Store获取DS1

相反,您希望每次运行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); 构造函数代码,而不是在设置{{1}}原型时运行一次:

{{1}}

答案 1 :(得分:2)

This is because in Javascript object are not copied by value but only by reference。现在,孩子的原型(这里是ds1,ds2)和父母指向同一个对象,当孩子修改原型时,父母会得到改变,兄弟姐妹也是如此。 Inheritance in javascript可以通过创建空函数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)即可继承; Inheritance and prototype chain

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

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

当您从d1d2调用/获取变量时,它会查看是否有addData。他们没有。然后js进入__prototype。嘿,new Store在那里!它有addData吗?是!叫它......

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