JavaScript学习笔记(八):闭包
0 目录
- 闭包的定义
- 闭包形成的条件
- 闭包的作用
- 闭包的应用
1 闭包的定义
闭包就是能够读取其他函数内部变量的函数。
本质上是将函数内部和外部连接起来的桥梁。
2 闭包形成的条件
简单的来说,当内部函数被保存到外部时,将会形成闭包。闭包会导致原有作用域链不释放,造成内存泄露(过多地占用系统资源)。
具体来讲,有以下几个方面:
- 两个函数嵌套
- 把子函数保存到父函数的外部(通常是保存到全局)
- 在外部执行保存出来的那个子函数,这个子函数一定能访问父函数环境里的变量(形成闭包)
简单的闭包示例:
function a(){
var i = 123;
function b(){
console.log(i);
}
return b;
}
var c = a();
c();
上述函数的运行结果为:123.
内部的函数b被return到外部,用c来接收。此时c===b,所以执行函数c时,就相当于执行函数b
而函数b是在函数a的执行阶段被定义的,所以函数b在被定义时,引用了函数a的执行期上下文(AO对象),而这个执行期上下文里就包含了在函数a内部定义的变量(上述代码为变量i)。当函数b被保存到外部时,这个执行期上下文也被保存到了外部。所以当函数b在外部执行时,可以访问到变量i
3 闭包的作用
- 实现公有变量
- 可以作为存储结构
- 可以实现封装
- 模块化开发,防止污染全局变量
闭包还会使得Javascript的垃圾回收机制不会收回父函数所占用的资源,因为父函数的内部函数的执行需要依赖父函数中的变量。其形成的效果就是,子函数的生命周期比父函数的长
4 闭包的应用
利用闭包实现函数累加器(作用1:实现公有变量):
function a(){
var num = 100;
function b(){
num++;
console.log(num);
}
return b;
}
var c = a();
c(); //输出结果为:101
c(); //输出结果为:102
两次函数c的执行,修改的都是同一个函数a执行期上下文里的属性num
用闭包作为存储结构:
function eater(){
var food = "";
var obj = {
eatFood : function(){
console.log("I am eating " + food);
food = "";
},
addFood : function(newFood){
food = newFood;
}
}
return obj;
}
var person = eater();
person.addFood("fried chicken");
person.eatFood(); //输出结果为:"I am eating fried chicken"