使用Javascript中的函数生成非实例化函数

ebd*_*vis 5 javascript inheritance

我有以下代码:

function Rune(){
    this.subSpells = [];
}
function Modifier(){
    this.type = "modifier";
}
Modifier.prototype = new Rune();

function RuneFactory(effect, inheritsFrom, initialValue){
    var toReturn = function(){}; 
    toReturn.prototype = new inheritsFrom();
    toReturn.prototype.subSpells[effect] = initialValue;
    return toReturn;
}

Duration = RuneFactory("duration", Modifier, 1);
Quicken = RuneFactory("quicken", Modifier, 1);

x = new Duration();
y = new Quicken();
Run Code Online (Sandbox Code Playgroud)

x.subSpells.duration和x.subSpells.quicken都等于1.与y相同.我希望x.subSpells.quicken和y.subSpells.duration未定义.

如果我为Duration和Quicken定义执行以下操作,我会得到我想要的行为.

Duration = RuneFactory("duration", Rune, 1);
Quicken = RuneFactory("quicken", Rune, 1);
Run Code Online (Sandbox Code Playgroud)

我认为双重继承存在问题.任何人都可以告诉我如何更改我的RuneFactory代码,使其适用于双重继承和/或解释什么是破坏?如果可能的话,我想避免使用框架.

谢谢!

Giv*_*ivi 3

在 Modifier 函数中添加以下行Rune.apply(this, arguments);,因为subSpells在原型级别定义,所以 Rune 的所有实例都引用同一对象。
并且,将类型subSpells从数组更改为对象。

正如wared所提到的,如果使用寄生组合继承模式会更好。

我认为双重继承存在问题” - 不!

首先,不存在双重继承这样的事情,您遇到与 Modifier 构造函数相同的问题,您的实例引用相同的subSpells对象(在您的情况下为数组。阅读原始值与引用值引用和值, 它是关于 .NET 的,但基本编程原理是一样的)。

查看JavaScript .prototype 是如何工作的?


看看jsFiddle

function inheritPrototype(subType, superType) {
    var prototype = Object.create(superType.prototype, {
        constructor: {
            value: subType,
            enumerable: true
        }
    });

    subType.prototype = prototype;
}

function Rune() {
    this.subSpells = {};
}

function Modifier() {
    Rune.apply(this, arguments);
    this.type = "modifier";
}

inheritPrototype(Modifier, Rune);

function RuneFactory(effect, inheritsFrom, initialValue) {
    function toReturn() {
        inheritsFrom.apply(this, arguments); // you should bind this
        this.subSpells[effect] = initialValue;
    }
    inheritPrototype(toReturn, inheritsFrom);
    return toReturn;
}

Duration = RuneFactory("duration", Modifier, 1);
Quicken = RuneFactory("quicken", Modifier, 1);

x = new Duration();
y = new Quicken();

console.log(x.subSpells.duration); // 1
console.log(x.subSpells.quicken); // undefined

console.log(y.subSpells.duration); // undefined
console.log(y.subSpells.quicken); // 1
Run Code Online (Sandbox Code Playgroud)