闭包的定义
闭包 是指有权访问另一个函数作用域中的变量的函数.(JS 高级程序设计)
看到这红宝书上关于闭包的解释, 起初一脸懵逼, 读懂之后其实并不难. 要彻底了解闭包, 首先必须了解下面的几个概念:
执行环境: 每个函数都有自己的执行环境. 当执行函数时, 函数的环境就会被推入一个环境栈中. 而在函数执行后, 栈将其环境弹出, 把控制权返回给之前的执行环境.
变量对象: 每个执行环境都有一个与之关联的变量对象, 环境中定义的所有变量和函数都保存在这个对象中. 当执行函数时, 变量对象会变成活动对象.
作用域链: 当代码在一个环境中执行时, 会创建变量对象的一个作用域链. 作用域链的用途, 是
保证对执行环境有权访问的所有变量和函数的有序访问. 作用域链的前端, 始终都是当前执行的代码所
在环境的变量对象. 如果这个环境是函数, 则将其活动对象作为变量对象.
执行环境和变量对象的概念容易理解, 但是怎么理解作用域链呢. 可以参考下图:
image
类似于同心圆结构, 每一层假设是一个函数, 上面都拥有与此层函数关联的变量对象; 假设当执行到最里面那个函数, 那么作用域链可以看做是图中一条由内到外的线, 最前端的就是它本身, 最后端就是全局执行环境. 那么它有什么用呢, 就是当你访问一个变量的时候, 就会沿着作用域链一层层往外查找, 直到找到为止, 如果到了最外层即全局执行环境下还没找到则报错.
闭包的实现
下面通过具体例子来解释:
- function a() {
- var text = '呵呵哒';
- return function () {
- console.log(text);
- }
- }
- var b = a();
- b();
当 a() 函数被执行后返回了一个匿名函数, 这个匿名函数的作用域链上有引用到 a() 执行环境的活动对象属性 text(不知道活动对象是什么的请看上面变量对象的解释).a() 函数执行完就马上被销毁了, 但是这个函数的变量对象仍然被 b 所引用, 所以它的变量对象不会被垃圾回收机制处理掉, 而是会留在内存中. 这就形成了一个闭包. 最后执行 b() 依然能读取到已经被销毁的 a 函数的定义的 text 变量.
我们换个更清晰的例子:
- function a() {
- var i = 0;
- return function () {
- console.log(i++);
- }
- }
- var b = a();
- b(); //0
- b(); //1
- b(); //2
这个例子三次调用 b() 会分别输出 0, 1, 2, 是因为 a() 的变量对象被 return 的闭包函数引用着, 所以 i 会一直留在内存中, 并只能被闭包函数所访问. 这个闭包函数被赋值给了 b, 所以 b() 能对 i 变量进行自增计算.
闭包的作用
什么, 你问我闭包有什么用?
好处就是类似于搭起一条沟通的桥, 闭包可以读取函数内部的变量; 并且让这个变量留在内存中而不会污染到全局变量.
坏处呢消耗内存, 如果一直不释放这个闭包就会一直占用着内存. 那要怎么释放呢? 很简单, 和函数一样赋值 null 就可以了.(b = null)
最后感谢观看~
我是 @一只有趣的程序猿 我叫大友~
来源: http://www.jianshu.com/p/2fa4e8a1eaf9