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