在对象上使用单独的init函数有什么好处?

时间:2014-10-17 03:05:27

标签: javascript

我的意思是这样的代码:

 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方法并在构造函数中进行所有初始化?

2 个答案:

答案 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函数看起来像最简单的解决方案,需要最少的代码而不需要额外的库或新版本的语言。