JavaScript中的原型对象创建被认为是强大的(我听说它很高效,如果使用得当,它的表现力非常强)。但出于某种原因,我发现它经常让我绊倒,而不是它对我有帮助。
对于涉及原型的对象创建模式,我遇到的主要问题是没有办法绕过对this的需要。主要原因是除了非常原始之外的任何对象,例如通过异步API调用填充自身的对象,this由于作用域的改变而崩溃。
因此,我使用原型对象创建对象,我从一开始就知道所有的东西。
但对于需要这样做的对象,例如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")
};
};因为这将完全替换该函数。为了解决这个问题,我提出了以下解决方案(您也可以在这里查看:http://jsfiddle.net/pellepim/mAGUg/9/)。
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.好了,我要问一个问题。我是不是完全偏离目标了,还是我说对了?明显的缺点是什么?
发布于 2011-11-17 18:14:18
不,你没有偏离目标。但那个轮子也不是你发明的。这种类型的ECMAscript继承在Doug Crockfords的书Javascript: The good parts中变得非常有名。
这是一个很好的模式,它很好地使用了闭包来保护私密性。但是,您仍然可以选择您喜欢的模式(纯原型继承、伪经典模式)。
有了ES5和新的可能性,如Object.create()和Object.defineProperties(),Object.freeze()等等,我们也有更多原型方法的保护和隐私的好方法。就我个人而言,我仍然更喜欢并喜欢伪经典的方式,使用闭包来做事情。
警告仍然可能是函数调用开销,这通常可以避免使用简单的原型继承。我们需要进行更多的调用才能将事情做好(如果事情变得更好的话)。尽管如此,闭包仍然被认为是有点贪婪的内存,如果我们草率地使用它们或者忘记清理这里和那里的引用,可能会导致泄漏。我现在没有这方面的任何参考资料,但我坚信最新的js引擎使用闭包并不会像很多一样慢很多。
https://stackoverflow.com/questions/8165181
复制相似问题