历史
模块模式最早是在 2003 年提出来的,后来由 Douglas・Crockford (道格拉斯・克劳克福德)推广。
Douglas・Crockford 著有《JavaScript 语言精粹》,相信很多人也看过。同时他还是 JSON、JSLint、JSMin 等工具的发明人,对 web 技术的发展功不可没。
什么是模块模式?
模块模式是一种解决软件中私有和公有的封装问题的方法。
通过这种模式,我们不仅可以解决公有/私有变量和方法封装的问题,还可以大大降低命名冲突的概率。
示例
首先,等号的右边是一个匿名的立即调用函数表达式,并且内部返回一个对象。这样就可以采用闭包的方式,封装内部的“私有”状态和组织。
等号的左边是一个全局变量,将右边返回的对象赋值给这个全局变量,这样就相当于在全局作用域仅暴露了一个接口,这个全局变量也就类似于一个命名空间,用来解决命名冲突的问题。
var myNameSpace = (function() {
// 私有变量
var privateVar = 0
// 私有方法
var privateMethod = function(foo) {
console.log(foo)
}
return {
// 公有变量
publicVar: 'foo',
// 公有方法
publicMethod: function(bar) {
// 修改私有变量
privateVar++
// 调用私有方法
privateMethod(bar)
}
}
})()
// 使用
console.log(myNameSpace.publicVar)
myNameSpace.publicMethod('bar')
上面的示例就是一个简单模块模式的实现。
优点
对代码整体性封装、支持数据私有化。
缺点
如果开始确定了数据的私有和公有,后期更改需要更改每个使用它的地方。
无法对私有成员进行自动化单元测试。
[扩展] 未来
现在已经有提案,向 JS 中引入 private fields ,用 #
符号来表示私有访问修饰符。那么用 #
修饰的变量和方法,在外部调用的时候就会报错。这样我们就可以把示例做个修改。
class MyNameSpace {
// 私有变量
#privateVar = 0
// 公有变量
publicVar = 'foo'
// 私有方法
#privateMethod (foo) {
console.log(foo)
}
// 公有方法
publicMethod (bar) {
// 修改私有变量
this.privateVar++
// 调用私有方法
this.privateMethod(bar)
}
}
// 使用
const mySpace = new MyNameSpace()
console.log(mySpace.publicVar)
mySpace.publicMethod('bar')