在JavaScript中用IIFE实现Singleton模式



以前在我公司工作的员工使用以下形式的Singleton模式在JavaScript中创建和获取UI组件:

getDetailForm: function() {
this.getDetailForm = (function() {
var form = // form creation logic
return function() {
return form;
};
}());
return this.getDetailForm();
}

是否有任何理由使用以下标准方式的变化?

getDetailForm: function() {
var form;
if (!form) {
form = // form creation logic
}
return form;
}

第二个代码块不会记住变量form的值:每次调用函数getDetailForm时,它代表一个新的闭包,并且在该范围内创建一个新变量form-每次都以undefined开始。

查看以下如何在每次调用上打印"init">

var o = {
getDetailForm: function() {
var form;
if (!form) {
form = 'form'; // form creation logic
console.log('init');
}
return form;
}
}
console.log(o.getDetailForm());
console.log(o.getDetailForm());

您可以通过在singleton对象的范围中声明表单来实现它,为此,您可以使用构造函数来实例化该对象,同时这也是窗体变量的闭包:

var o = new function () {
var form;
this.getDetailForm = function() {
if (!form) {
form = 'form'; // form creation logic
console.log('init');
}
return form;
}
};
console.log(o.getDetailForm());
console.log(o.getDetailForm());

看看输出现在如何只显示"init">一次。

差异

您提供的第一个版本有一个小小的优势:在第一次调用后,函数将被一个非常基本的函数所取代:

function() {
return form;
};

在该函数中甚至没有if。它只是一个return。因此,有人可能会争辩说,这是最好的:在该函数的任何后续调用中,对if条件的求值都不会损失任何性能,当您多次调用该方法时,除了第一次调用外,它总是返回相同的结果。

然而,如果您将值直接分配给构造函数中的形式,那么构造函数模式也可以实现这一点。然后您就不再需要方法中的if了,因为初始化已经在构造函数中进行了。

请注意,这并不完全相同,因为现在构造函数正在繁重地将表达式(可能非常耗时)分配给表单。您提供的第一个代码的优点是,只有在第一次调用函数时才能执行此操作,您可以认为这是一个优点:"不要在可能永远不会使用的东西上浪费时间"。

最新更新