闭包的应用 – 自定义JS模块
JS模块的本质就是js文件
我们可以将所有的数据和功能都封装在一个函数内部(私有的),只向外暴露一个包含n个方法的对象或函数(一个容器),模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能即可
实现一:
通过return一个容器来进行暴露。
模块:
function myModule() {
//私有数据
var msg = 'My NEFU'
//操作数据的函数
function doSomething() {
console.log('doSomething() '+msg.toUpperCase())
}
function doOtherthing () {
console.log('doOtherthing() '+msg.toLowerCase())
}
//向外暴露对象(给外部使用的方法)
return {
doSomething: doSomething,
doOtherthing: doOtherthing
}
}
使用端:
<script type="text/javascript" src="myModule.js"></script>
<script type="text/javascript">
var module = myModule()
module.doSomething()
module.doOtherthing()
</script>
实现二:
通过立即执行函数,将方法变成为window的属性,使用的时候可以省略window
模块:
(function () {
//私有数据
var msg = 'My NEFU'
//操作数据的函数
function doSomething() {
console.log('doSomething() '+msg.toUpperCase())
}
function doOtherthing () {
console.log('doOtherthing() '+msg.toLowerCase())
}
//向外暴露对象(给外部使用的方法)
window.myModule2 = {
doSomething: doSomething,
doOtherthing: doOtherthing
}
})()
使用端:
<script type="text/javascript" src="myModule2.js"></script>
<script type="text/javascript">
myModule2.doSomething()
myModule2.doOtherthing()
</script>
注:
将模块的代码这样写更好:
(function (window) {
//私有数据
var msg = 'My NEFU'
//操作数据的函数
function doSomething() {
console.log('doSomething() '+msg.toUpperCase())
}
function doOtherthing () {
console.log('doOtherthing() '+msg.toLowerCase())
}
//向外暴露对象(给外部使用的方法)
window.myModule2 = {
doSomething: doSomething,
doOtherthing: doOtherthing
}
})(window)
如此在压缩代码的时候,会将所有window替换为单个字母,而原来的代码则会原模原样的进行存储。
闭包的缺点以及解决
缺点:
- 函数执行完后, 函数内的局部变量没有释放, 占用内存时间会变长
- 容易造成内存泄露
解决:
- 能不用闭包就不用
- 及时释放(让其指向null)
例如:
<script type="text/javascript">
function fn1() {
var arr = new Array[100000]
function fn2() {
console.log(arr.length)
}
return fn2
}
var f = fn1()
f()
f = null //让内部函数成为垃圾对象-->回收闭包
</script>
闭包的面试题
<script type="text/javascript">
//代码片段一
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //?
//代码片段二
var name2 = "The Window";
var object2 = {
name2 : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name2;
};
}
};
alert(object2.getNameFunc()()); //?
</script>
答案:
第一个问号处:the window
第二个问号处: my object
要注意:
片段一没有形成闭包,片段二是有闭包的。此处涉及前面的一个知识点this: