我来自C++ /Objective背景,我正在努力学习如何在Javascript中正确高效地再现继承和封装模式。我读了很多书(克罗克福德等)虽然有很多如何实现其中一个的例子,但我很难将它们结合在一起,而不引入重大的负面因素。
目前,我有这样的代码:
var BaseClass = (function() {
function doThing() {
console.log("[%s] Base-class's 'doThing'", this.name);
}
function reportThing() {
console.log("[%s] Base-class's 'reportThing'", this.name);
}
return function(name) {
var self = Object.create({});
self.name = name;
self.doThing = doThing;
self.reportThing = reportThing;
return self;
}
}());
var SubClass = (function(base) {
function extraThing() {
console.log("[%s] Sub-class's 'extraThing'", this.name);
}
function doThing() {
console.log("[%s] Sub-class's replacement 'doThing'", this.name);
}
return function(name) {
// Create an instance of the base object, passing our 'name' to it.
var self = Object.create(base(name));
// We need to bind the new method to replace the old
self.doThing = doThing;
self.extraThing = extraThing;
return self;
}
}(BaseClass));它主要做我想做的事:
// Create an instance of the base class and call it's two methods
var base = BaseClass("Bert");
base.doThing(); // "[Bert] Base-class's 'doThing'"
base.reportThing(); // "[Bert] Base-class's 'reportThing'"
var other = BaseClass("Fred");
// Create an instance of the sub-class and call it's three methods (two from the base, one of it's own)
var sub = SubClass("Alfred");
sub.doThing(); // "[Alfred] Sub-class's replacement 'doThing'"
sub.extraThing(); // "[Alfred] Sub-class's 'extraThing'"
sub.reportThing(); // "[Alfred] Base-class's 'reportThing'"但是,(至少!)两个问题:
我正在替换原型的实现,如下所示:
Object.getPrototypeOf(oneInstance).reportThing = function() { ... }
otherInstance.reportThing() // Original version is still called这也许不是一个重大的问题,但它使我怀疑我的理解。
但是,私有变量是我想要高效实现的东西。变量隐藏的模块模式在这里没有帮助,因为它会导致每个对象都存在函数定义。我可能错过了一种组合模式的方法,那么有没有一种在不重复函数的情况下实现私有变量的方法?
发布于 2015-02-17 12:52:04
这通常是我在JavaScript中处理继承和封装的方式。defclass函数用于创建一个不从任何其他类继承的新类,extend函数用于创建一个扩展另一个类的新类:
var base = new BaseClass("Bert");
base.doThing(); // "Bert BaseClass doThing"
base.reportThing(); // "Bert BaseClass reportThing"
var sub = new SubClass("Alfred");
sub.doThing(); // "Alfred SubClass replacement doThing"
sub.extraThing(); // "Alfred SubClass extraThing"
sub.reportThing(); // "Alfred BaseClass reportThing"
var other = new SubClass("Fred");
SubClass.prototype.reportThing = function () {
console.log(this.name + " SubClass replacement reportThing");
};
other.reportThing(); // Fred SubClass replacement reportThing<script>
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
function extend(constructor, keys) {
var prototype = Object.create(constructor.prototype);
for (var key in keys) prototype[key] = keys[key];
return defclass(prototype);
}
var BaseClass = defclass({
constructor: function (name) {
this.name = name;
},
doThing: function () {
console.log(this.name + " BaseClass doThing");
},
reportThing: function () {
console.log(this.name + " BaseClass reportThing");
}
});
var SubClass = extend(BaseClass, {
constructor: function (name) {
BaseClass.call(this, name);
},
doThing: function () {
console.log(this.name + " SubClass replacement doThing");
},
extraThing: function () {
console.log(this.name + " SubClass extraThing");
}
});
</script>
阅读以下答案,了解JavaScript中的继承是如何工作的:
解释了原型和构造器的区别。此外,它还展示了原型和类是如何同构的,以及如何在JavaScript中创建“类”。
希望这能有所帮助。
发布于 2015-02-17 12:36:38
简单的配方如下:
function BaseClass(someParams)
{
// Setup the public properties, e.g.
this.name = someParams.name;
}
BaseClass.prototype.someMethod = function(){
// Do something with the public properties
}现在继承是这样发生的。
function SubClass(someParams)
{
// Reuse the base class constructor
BaseClass.call(this, someParams);
// Keep initializing stuff that wasn't initialized by the base class
this.anotherProperty= someParams.anotherProperty;
}
// Copy the prototype from the BaseClass
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
// Start extending or overriding stuff
SubClass.prototype.someMethod = function(){
// In case you still wanna have the side effects of the original method
// This is opt-in code so it depends on your scenario.
BaseClass.prototype.someMethod.apply(this, arguments);
// Override the method here
}摘自:JavaScript
P.S. Object.create可能并不是所有旧浏览器都支持的,但是不要担心,这个链接中有一个多填充。对象/对象/创建
发布于 2015-02-17 11:28:18
如果要保留原型链,则必须重写并使用.prototype:示例: Main:
function BaseClass(){
}
BaseClass.prototype.doThing = function(){...}SubClass:
function SubClass(){
}
SubClass.prototype= new BaseClass();
SubClass.prototype.extraThing = function(){};现在,每当您更改extraThing或doThing时,就会到处替换它。name属性可以作为公共变量访问(它不是静态的)。
如果你想让它是静态的,你必须把它放在原型中。
如果你希望它是私有的,你应该让它在本地发挥作用:
function BaseClass(nameParam){
var name = nameParam;
}要创建一个对象,只需调用该函数:
var testObj = new BaseClass("test");
testObj.doThing();如果您想将私有变量与可重写函数组合起来,您可能会找到您的回答这里。但是如果您能够重写访问私有变量的函数,那么它就不再是真正的私有变量了。
https://stackoverflow.com/questions/28558503
复制相似问题