【问题标题】:javascript: create an object that inherits from the prototypes of more than one constructorjavascript:创建一个从多个构造函数的原型继承的对象
【发布时间】:2011-05-13 19:36:22
【问题描述】:

假设我有两个构造函数:

A = function () {
    this.x = 'x';
};
A.prototype.a = 'a';

B = function () {
    this.y = 'y';
};
B.prototype.b = 'b';

我怎样才能创建一个对象ab,它将继承自 两者的原型?所以下面的例子可以工作:

ab.a === 'a'; // true
ab.b === 'b'; // true
A.prototype.a = 'm';
ab.a === 'm'; // true
B.prototype.b = 'n';
ab.b === 'n'; // true

谢谢

【问题讨论】:

  • 多重继承可能非常危险,并且在大多数情况下表明设计不佳。你想做什么?这些变化很好,有更好的解决方案。
  • 多重继承是个工具,就像goto...

标签: javascript inheritance prototype constructor


【解决方案1】:

下面是一个链接,描述了一种在javascript中实现多重继承的方法:

http://www.polyglotinc.com/AJAXscratch/Class/InterfacesFromScratch.html

看起来很复杂。如前所述,找到另一种方法可能更好/更安全/更容易。

【讨论】:

    【解决方案2】:

    你不能,只有一个原型链。你基本上有三个选择:

    从一个继承,复制另一个

    单个对象上的属性而言,您所能做的就是从其中一个原型继承并复制另一个原型的属性。显然这不是您想要的,因为您没有复制属性的实时引用方面,但您可以在单个对象上拥有这些属性。

    作曲

    另一种选择是作曲

    var ab = {
        aness: new A(),
        bness: new B()
    };
    
    ab.aness.a === 'a'; // true
    ab.bness.b === 'b'; // true
    A.prototype.a = 'm';
    ab.aness.a === 'm'; // true
    B.prototype.b = 'n';
    ab.bness.b === 'n'; // true
    

    所以现在,ab 在其aness 属性中作为A 方面(称之为“A-ness”),在其属性中作为B 方面(称之为“B-ness”) bness 财产。

    通常当人们认为“我需要多重继承”时,组合是一个很好的选择(即使在允许多重继承的系统中也是如此)。请注意,并非总是如此,但经常如此。

    如果您需要向 ab 的 A-ness 或 B-ness 添加还可以访问其他方面的函数,您可以使用闭包来实现。例如,如果您将一个对象传递给第三方库,该库希望看到一个 A 实例并调用它的 foo 函数,并且我们想要在 foo 中做一些不同的事情,则可能会出现这种情况我们B 方面的一些状态。例如:

    function AB() {
        var aness, bness;
    
        this.aness = aness = new A();
        this.bness = bness = new B();
    
        // `foo` returns the `a` property of our composite if
        // it's been changed; otherwise, it returns the `b`
        // property of our composite.
        aness.foo = function() {
            // We want to use `A`'s normal `foo` unless our
            // B-ness `b` property is 42 for some reason.
            if (bness.b === 42) {
                // Our magic number, handle locally.
                return "The answer";
            }
            // Not our magic number, let `A` handle it
            return A.prototype.foo.call(this);
        };
    }
    var ab = new AB();
    

    但请注意上述模式,因为它会为AB 构造函数生成的每个实例 创建一个新函数。如果有很多,可能会成为内存问题。

    在这一点上,我们开始误入继承链和超级调用,我在this blog post 中有更详细的讨论。

    B 链接到A

    如果您是AB 的设计者,可能B 继承自A,然后您的ab 可以由B 构造函数:

    A = function () {
        this.x = 'x';
    };
    A.prototype.a = 'a';
    
    B = function () {
        this.y = 'y';
    };
    B.prototype = new A();
    B.prototype.b = 'b';
    
    ab = new B();
    
    ab.a === 'a'; // true
    ab.b === 'b'; // true
    A.prototype.a = 'm';
    ab.a === 'm'; // true
    B.prototype.b = 'n';
    ab.b === 'n'; // true
    

    ...但这意味着 所有 B 对象也是 A 对象,这可能不是您想要的。


    题外话:我没有在上面添加vars,因为假设它们不存在是有原因的(例如,它们已经在你的代码中声明了不显示)。

    题外话2:除非你有充分的理由,否则我总是recommend using named functions 而不是匿名的(你分配给AB 的函数是匿名的)。

    【讨论】:

    • 但实际上,我可以看到如何选择一个构造函数进行继承并使用组合添加其余构造函数可以满足我的需求。谢谢
    • @TheOsp:完美。 :-) 很高兴有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 2014-01-01
    • 2015-03-24
    • 1970-01-01
    相关资源
    最近更新 更多