我的意思是这样的代码:
function MyObject(x, y, z) {
this.init(x, y, z);
}
MyObject.prototype = {
constructor: MyObject,
init: function(x, y, z) {
// actually use x, y, z
},
other methods
};
为什么不只是没有init方法并在构造函数中进行所有初始化?
答案 0 :(得分:0)
无。真的,没有。您的构造函数不会执行init
以外的任何操作。这或多或少是反模式。
初始化对象的方法的优点是可以多次调用(在同一对象上),用于对象池或仅重置它。但是,每个精心设计的JS对象都已经拥有了这个方法:它被称为.constructor()
。它是构造函数,默认情况下可以在自己的原型上使用,并且如果需要,通常会明确地将其置于其上(如在您的示例中所做的那样)。
这意味着使用额外的init
方法相当无用,通常效率较低且更冗长。除非您使用此详细程度来强调(通过名称和声明的样式)将其用作方法,并可能简化计划的重构,以便实际的构造函数可以更多 init
方法(例如创建常量字段)。但是,我不会过早地这样做,但是,yagni。
答案 1 :(得分:0)
在javascript中,遗憾的是没有干净的方法在构造函数链中传递参数,因为构造函数继承自对象,而不是其他构造函数。例如,请考虑以下事项:
function Person (name) {
this.name = name;
}
function Accountant () {}
Accountant.prototype = new Person('');
现在,如果你想创建一个Accountant
那里没有一个干净的方法给他一个名字:
var x = new Accountant();
当然,在这个简单的例子中,你可以在创建他之后手动设置他的名字:
x.name = 'Andy';
但现实世界的代码可能并不总是那么容易解决。一些对象将状态保存在闭包中,这意味着您无法将参数传递回父的构造函数,因为您在定义子对象的原型时已经创建了父对象。
一个解决办法当然是根本不使用继承,而是使用装饰器函数,就好像它们是构造函数一样:
function new_person (name) {
var self = {};
self.name = name;
return self;
}
function new_accountant (name) {
var self = new_person(name);
return self;
}
这种设计模式通常称为寄生遗传。请注意,在此设计模式中,我们不使用关键字new
。
如果您仍想使用正确的继承,另一种解决方法是让对象具有init
函数,任何想要继承它的构造函数都可以调用它:
function Person (name) {
this.init(name);
}
Person.prototype.init = function (name) {
this.name = name;
}
function Accountant (name) {
this.init(name);
}
Accountant.prototype = new Person('');
当然还有其他更奇特的解决方法。这是javascript,你只受你的创造力的限制。但是对于原型继承,init函数看起来像最简单的解决方案,需要最少的代码而不需要额外的库或新版本的语言。