本文探讨在JavaScript中因语言限制而不得不使用闭包的场景,以变量只初始化一次为例。对比常规类实现、使用IIFE闭包以及使用self变量的三种方案,指出使用self变量在可扩展性上优于闭包,便于后续线性扩展不同操作而无需重写代码。
JavaScript中闭包的主动与被动特性
JavaScript中的闭包既是一个主动发展的特性,也是一个被动发展的特性。一方面,利用闭包可以更好地解决某些问题;另一方面,为了解决特定问题,JavaScript有时也不得不借助闭包来勉强实现功能。
对于闭包能更好解决问题的情况,这里不予讨论,因为如果闭包能更优地解决问题,自然应当优先使用闭包。
本文重点讨论的是后者,即由于JavaScript本身的限制,不得不通过闭包来曲折解决的问题,例如“变量只初始化一次”这类需求。
在其他常规编程语言中,此类问题通常有直接的解决方式。
具体代码实现如下:
class Class{
function init(){
this.n = 0;
}
function func(){
this.n ++;
return this.n;
}
}
var obj = new Class();
使用闭包解决变量初始化问题
在JavaScript中,常见的解决方式是使用闭包(立即执行函数表达式)。
相关代码如下:
var obj = {
func : (function(){
var n = 0;
return function(){
n ++;
return n;
}
})()
}
通过self变量消除闭包的优势
然而,我更建议采用另一种方法,即通过消除闭包来实现。
具体代码示例如下:
function Class(){
var self = this;
self.n = 0;
self.func = function(){
self.n ++;
return self.n;
}
}
var obj = new Class();
采用后一种方法(使用self变量)具有更好的可扩展性。当需要实现对同一变量的不同操作时,后一种方法只需再定义一个不同的函数即可实现简单的线性扩展;而前一种方法(使用闭包)则需要完全重写代码。这也是为什么在开发中经常听到“重构”这一概念的原因之一。