1.闭包的应用 : 定义JS模块
- 具有特定功能的js文件
- 将所有的数据和功能都封装在一个函数内部(私有的)
- 只向外暴露一个包信n个方法的对象或函数
- 模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能
方式1:先准备一个myModule.js文件:
function myModule() {
//私有数据
var msg = 'My atguigu'
//操作数据的函数
function doSomething() {
console.log('doSomething() '+msg.toUpperCase())
}
function doOtherthing () {
console.log('doOtherthing() '+msg.toLowerCase())
}
//当需要暴露多个方法时使用对象进行封装
//向外暴露对象(给外部使用的方法)
return {
doSomething: doSomething,
doOtherthing: doOtherthing
}
}
该js中使用了闭包
在html中调用:
先引入
再通过对象调用方法
<script type="text/javascript" src="myModule.js"></script>
<script type="text/javascript">
var module = myModule()
module.doSomething()
module.doOtherthing()
</script>
方式2(推荐使用) : 在没有Module.js中使用匿名函数自调用的方式暴露:
//通过匿名函数自定义
(function () {
//私有数据
var msg = 'My atguigu'
//操作数据的函数
function doSomething() {
console.log('doSomething() '+msg.toUpperCase())
}
function doOtherthing () {
console.log('doOtherthing() '+msg.toLowerCase())
}
//将方法添加到window中,来向外暴露
window.myModule2 = {
doSomething: doSomething,
doOtherthing: doOtherthing
}
})()
在html中通过js文件直接使用:
<script type="text/javascript" src="myModule2.js"></script>
<script type="text/javascript">
myModule2.doSomething()
myModule2.doOtherthing()
</script>
2.闭包的缺点
- 函数执行完后, 函数内的局部变量没有释放, 占用内存时间会变长
- 容易造成内存泄露(内存占用却不用)
3.闭包的解决方法
- 能不用闭包就不用
- 及时释放
<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>
4. 内存溢出
- 一种程序运行出现的错误
- 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误
var obj = {}
for (var i = 0; i < 10000; i++) {
obj[i] = new Array(10000000)
console.log('-----')
}
5. 内存泄露
- 占用的内存没有及时释放 ,可以继续运行不报错
- 内存泄露积累多了就容易导致内存溢出
- 常见的内存泄露:
- 意外的全局变量
- 没有及时清理的计时器或回调函数
- 闭包
// 意外的全局变量
function fn() {
a = new Array(10000000)//应该是用var定义变量 避免成为全局变量
console.log(a)
}
fn()
// 没有及时清理的计时器或回调函数
var intervalId = setInterval(function () { //启动循环定时器后不清理
console.log('----')
}, 1000)
// clearInterval(intervalId) //使用clearInterval清理定时器
// 闭包
function fn1() {
var a = 4
function fn2() {
console.log(++a)
}
return fn2
}
var f = fn1()
f()
// f = null //!!!!让内部函数成为垃圾对象-->回收闭包
6. 闭包相关面试题
调用object.getNameFunc()返回一个函数function
执行function()返回this.name 由于是通过方法进行调用 返回全局变量 (通过对象调用 返回局部变量)
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); // the window
调用object.getNameFunc()返回一个函数function
执行function()返回that.name
由于that保存的是调用 getNameFunc是对象的值,所以返回局部变量 my object
有闭包–that
var name2 = "The Window";
var object2 = {
name2 : "My Object",
getNameFunc : function(){
var that = this;//!!常用 用一个变量保存当前调用函数的this对象
return function(){
return that.name2;
};
}
};
alert(object2.getNameFunc()()); //? my object
这里是引用
function fun(n,o) {
console.log(o)
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,?
注意点:
1 第一层与第三层为同一个函数,第二层为不同的函数
2 题中的 . 和 ;,一个是继续调用,一个是结束语句,还有赋值保留了当前的状态
具体解析可以点击查看