【问题标题】:Inheriting more than once, keeping members private per instance继承不止一次,每个实例保持成员私有
【发布时间】:2011-10-11 08:18:58
【问题描述】:

基本上,我想要做的是已经讨论过很多次的事情。但是,大多数示例仅具有从 ClassB 继承的 ClassA。我的情况很琐碎,但似乎没有在我找到的 JavaScript 主题中得到解决。

ClassB 扩展了 ClassA,它有一个成员。 ClassC 和 ClassD 扩展 ClassB。但是,当在 ClassC 的实例中设置唯一成员时,该成员也在 ClassD 的成员中设置。我们来看一个例子:

function ClassA(data) {
        var This = this;
        This._data = {};

        This._construct = function(data) {
            if( undefined === data ) {
                This._data = {};
                return true;
            }

            This._data = data;
        }


        This._construct(data);
    }

    function ClassB() {
    }
    ClassB.prototype = new ClassA();
    ClassB.prototype.constructor = ClassB;

    function ClassC() { // Extends ClassB
    }
    ClassC.prototype = new ClassB();
    ClassC.prototype.constructor = ClassC;

    function ClassD() { // Extends ClassB
    }
    ClassD.prototype = new ClassB();
    ClassD.prototype.constructor = ClassD;


    var objectC = new ClassC();
    var objectD = new ClassD();

    objectC._data['somevar'] = 'asdasdasd';
    console.log(objectC._data); // Object { somevar="asdasdasd"}
    console.log(objectD._data); // Object { somevar="asdasdasd"}

如果您在console.log(objectC._data); 行设置断点,您可能会在FireBug 的Watch 窗口中看到所有原型都设置正确。这真的很奇怪,因为很明显 ClassC 和 ClassD 的原型是使用 new 关键字创建的独立实例,因此不应该共享成员。谁能解释一下?

_construct() 函数可以从 ClassA 中删除,但没有任何效果。 var This = this 行可以去掉,所有后续对This 的引用都可以改为this,没有效果。

【问题讨论】:

  • 问题已解决。对于那些真正想知道自己在做什么的极客,请参阅this amazing article。我使用 jQuery,所以 this plugin 看起来是正确的解决方案。
  • 好吧,this plugin 很垃圾,漏洞百出,貌似被作者抛弃了。相反,请查看this one

标签: javascript oop inheritance


【解决方案1】:

您需要在每个类中调用 super 才能使此模式起作用。这样就可以了。

//Simplifying the construction part a bit.
function ClassA(data) {
    this._data = data || {};
}

function ClassB(data) {
    ClassA.call(this, data); //call super class (ClassA) constructor
    //here you can initialize any ClassB specific variables
}
ClassB.prototype = new ClassA();
ClassB.prototype.constructor = ClassB;

function ClassC(data) { // Extends ClassB
    ClassB.call(this, data); //call super class (ClassB) constructor
    //here you can initialize any ClassC specific variables
}
ClassC.prototype = new ClassB();
ClassC.prototype.constructor = ClassC;

function ClassD(data) { // Extends ClassB
    ClassB.call(this, data); //call super class (ClassB) constructor
    //here you can initialize any ClassD specific variables
}
ClassD.prototype = new ClassB();
ClassD.prototype.constructor = ClassD;


var objectC = new ClassC();
var objectD = new ClassD();

objectC._data['somevar'] = 'asdasdasd';

console.log(objectC._data); // Object { somevar="asdasdasd"}
console.log(objectD._data); // Object {}  -- empty for objectD

现在您可以看到_data 没有跨实例共享。

【讨论】:

  • _data = {}x = 'testmember'.. 有什么区别?我看不出有什么不同。但是,我作为对原始帖子的评论发布的文章详细解释了这一点。
  • @XedinUnknown 我只是指出x 不是跨实例共享的,而_data 是跨实例共享的。区别在于 _data 是一个“对象”,x 是一个“字符串”。再说一次,我不完全确定为什么会发生这种情况。顺便说一句,您发布的文章很好。谢谢你。
  • 在您的具体情况下,这是因为在 JavaScript 中,原始类型是通过值传递的,而对象是通过引用传递的。但是,因为在构建或多或少复杂的应用程序时,我们需要一致的可靠行为,所以您的方法不是解决方案 - 仅仅是因为它不是方法。如果我需要一个对象,我不能只使用一个原语。
  • @XedinUnknown 知道了。我相应地更新了答案,包括对super 的调用。您现在可以看到 _data 不再跨实例共享。
猜你喜欢
  • 2020-09-04
  • 2020-09-01
  • 2018-05-11
  • 1970-01-01
  • 2023-03-03
  • 2010-10-15
  • 2012-09-12
  • 2013-02-12
  • 2015-01-21
相关资源
最近更新 更多