Javascript 这种寄生遗传模式好吗?

Javascript 这种寄生遗传模式好吗?,javascript,design-patterns,Javascript,Design Patterns,JavaScript中的原型对象创建被认为是强大的(我听说它是高效的,如果使用正确的话,它的表现力非常强)。但出于某种原因,我发现它经常绊倒我,而不是帮助我 关于涉及原型的对象创建模式,我遇到的主要问题是,没有办法绕过this的需要。主要原因是对象超出了非常原始的范围,例如通过异步API调用填充自己的对象,此会由于范围的更改而崩溃 所以,我使用原型对象创建对象,我从一开始就知道所有的东西 但对于需要执行例如API调用以保持自身最新的对象,我完全跳过了prototype并使用直接的对象文本 当我觉

JavaScript中的原型对象创建被认为是强大的(我听说它是高效的,如果使用正确的话,它的表现力非常强)。但出于某种原因,我发现它经常绊倒我,而不是帮助我

关于涉及原型的对象创建模式,我遇到的主要问题是,没有办法绕过
this
的需要。主要原因是对象超出了非常原始的范围,例如通过异步API调用填充自己的对象,
会由于范围的更改而崩溃

所以,我使用原型对象创建对象,我从一开始就知道所有的东西

但对于需要执行例如API调用以保持自身最新的对象,我完全跳过了prototype并使用直接的对象文本

当我觉得需要扩展其中一个对象时,我使用了寄生继承:

var ROOT = ROOT || {};

ROOT.Parent = function () {
    var self = {
        func1 : function () {
            alert("func1")
        };
    }
    return self;
};

ROOT.Child = function () {
    var self = ROOT.Parent(); // This is the parasitizing

    self.func2 = function () {
        alert("func2")
    };

    return self;
};

var myChild = ROOT.Child();
myChild.func1(); // alerts "func1"
myChild.func2(); // alerts "func2"
使用此模式,我可以在
ROOT.Child
对象中重用
func1
的代码。但是,如果我想扩展
func1
中的代码,我有一个问题。也就是说,如果我想调用父级
func1
中的代码,也要调用我自己的
func1
中的代码,这种模式会带来挑战。我不能这样做:

ROOT.Child = function () {
    var self = ROOT.Parent();

    self.func1 = function () {
        alert("func2")
    };
};
因为这将完全取代该功能。为了解决这个问题,我提出了以下解决方案(您也可以在这里查看:)


好的,我应该问一个问题。我是不是完全偏离了目标,还是有什么事?明显的缺点是什么?

不,你没有偏离目标。但是你也没有发明轮子。这种类型的ECMAscript继承在Doug Crockfords的书《Javascript:The good parts》中非常有名

这是一种很好的模式,它很好地使用闭包来保持私有和受保护。然而,您仍然可以选择哪种模式(纯原型继承、伪经典)

有了ES5和新的可能性,如
Object.create()
Object.defineProperties()
Object.freeze()
,我们也有了更好的方法,通过更原型的方法来保护和隐私。就我个人而言,我仍然喜欢伪经典的方法,使用闭包来做事情


警告仍然可能是函数调用开销,通常可以避免使用普通原型继承。我们需要打更多的电话才能把事情做好(如果事情发展的话)。尽管如此,闭包还是被认为有点内存贪婪,如果我们草率地使用闭包,或者忘记清理这里和那里的引用,闭包可能是导致泄漏的一个原因。我现在没有任何参考资料,但我坚信最新的js引擎使用闭包的速度不会慢很多。

你从哪里听说基于原型的继承是有效的?基于类的方法使编译器和运行时更容易进行优化。(关于它的强大性和表现力没有争议)@Thilo-Author建议(我支持他),原型继承在javascript中是有效的,主要是因为它涉及跨多个对象使用相同的函数(通过原型).我只是对不同场景中的基准了解不够,无法捍卫任何关于不同对象创建模式效率的观点。我的原型方法的问题是,除非我描述的工件是完全原始的,否则我甚至不能让它为我工作。@WTK:哦,我明白了。反对撤回:-)是的,我从他的帖子中了解到了寄生遗传:。但除了基于原型的对象创建之外,我还没有看到他提出任何理由。事实上,他声称“学会了完全接受原型主义,并将自己从古典模式的束缚中解放出来。”:)他显然比我聪明。无论如何,您对
extend
方法有什么反馈吗?
var ROOT = {};

/**
 * This is the base function for Parasitic Inheritence
 */
ROOT.Inheritable = function () {
    var self = {
        /**
         * takes the name of a function that should exist on "self", and
         * rewires it so that it executes both the original function, and the method
         * supplied as second parameter.
         */
        extend : function (functionName, func) {
            if (self.hasOwnProperty(functionName)) {
                var superFunction = self[functionName];
                self[functionName] = function () {
                    superFunction();
                    func();
                };
            }
        },

        /**
         * Takes the name of a function and reassigns it to the function supplied
         * as second parameter.
         */
        replace : function (methodName, func) {
            self[methodName] = func;
        } 
    };

    return self;
};

/**
 * "Inherits" from ROOT.Inheritable
 */
ROOT.Action = function () {
    var self = ROOT.Inheritable();
    /**
     * I intend to extend this method in an inheriting object
     */
    self.methodToExtend = function () {
        alert("I should be seen first, since I get extended");  
    };
    /**
     * I intend to replace this method in an inheriting object
     */
    self.methodToReplace = function () {
        alert("I should never be seen, since I get replaced.");
    };
    return self;
};

/**
 * "Inherits" from ROOT.Action.
 */
ROOT.Task = function () {
    var self = ROOT.Action();

    self.extend('methodToExtend', function () {
       alert("I successfully ran the extended code too.");
    });

    /** 
     * I know it is completely unecessary to have a replace method, 
     * I could just as easily just type self.methodToReplace = function () ...
     * but I like that you see that you are actually replacing something.
     */
    self.replace('methodToReplace', function () {
        alert("I successfully replaced the \"super\" method.");
    });

    return self;
};

var task = ROOT.Task();

task.methodToExtend(); // I expect both the "base" and "child" method to run.
task.methodToReplace(); // I expect only the "child" method to run.