由来
揭示模块模式是对之前模块模式的一种改进。
在模块模式中,公有属性和方法都是写在被返回的字面量对象中,这样,如果想在闭包内部调用公有属性和方法,就需要通过暴露在全局变量中的对象名称去调用。
var nameSpace = (function(){
return {
// 公有属性
firstName: 'Peppa',
// 公有属性
lastName: 'Pig',
getFullName: function() {
return nameSpace.firstName + ' ' + nameSpace.lastName
}
}
})()
nameSpace.getFullName() // => "Peppa Pig"
就像上面实例中展示的,getFullName
方法中需要访问公有属性 firstName
和 lastName
,就必须通过 nameSpace
对象名去调用。
这样的确很别扭,如果想要给 nameSpace
换个对象名,就需要考虑闭包内部的调用。下面我们看看揭示模块模式是怎么优化的。
揭示模块模式
针对上面的模块模式的示例,我们用揭示模块模式做一番优化。
var nameSpace = (function(){
var firstName = 'Peppa'
var lastName = 'Pig'
function getFullName() {
return firstName + ' ' + lastName
}
return {
firstName: firstName,
lastName: lastName,
getFullName: getFullName
}
})()
nameSpace.getFullName() // => "Peppa Pig"
优化后的代码,我们将公有的变量和方法在返回前就做了处理,而返回的对象更加纯粹,增强了可读性。这也是揭示模块模式的优点。
同样揭示模块模式也有缺点。
var nameSpace = (function() {
function getFullName() {
return 'liMing'
}
// 私有方法
function sayHello() {
return 'hi~ ' + getFullName()
}
function firstMeet() {
console.log(sayHello() + ', I am zkk')
}
return {
getFullName: getFullName,
firstMeet: firstMeet
}
})()
nameSpace.firstMeet() // => "hi~ liMing, I am zkk"
上面是一段初次见面打招呼的封装, sayHello
是一个私有方法,但是它调用了 getFullName
这个公有方法,同时 firstMeet
方法调用了 sayHello
私有方法。
现在我需要改变打招呼的对象了,也就是我要修改 getFullName
方法了。
// ... 继续上面代码
nameSpace.getFullName = function() {
return 'Danny'
}
nameSpace.firstMeet() // => "hi~ liMing, I am zkk"
通过修改我们发现 nameSpace.getFullName
这个方法的确被覆盖了,但是最终的输出并没有改变。
这是因为我们虽然覆盖了返回值中的 getFullName
方法,但是私有方法 sayHello
真正调用的那个 getFullName
还是没有改变。这便是揭示模块模式存在的缺点。
所以到底采用原始的模块模式,还是揭示模块模式,必须依据场景来定。
以上就是揭示模块模式的介绍。