夺命雷公狗---javascript NO:30 闭包
1、什么是闭包
所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
例1:运行一下代码,得出结论:在全局作用域没有办法直接引用局部变量
<!DOCTYPE html> <html> <head> <meta charset=’utf-8′> <title></title> </head> <body> <script> function display(){ var i = 10;//局部变量 } display(); alert(i); //报错 </script> </body> </html>
原因:1)作用域不允许
2)受到js的垃圾回收影响
例2:有没有办法实现在全局作用域中引用局部变量,运行一下代码
<!DOCTYPE html> <html> <head> <meta charset=’utf-8′> <title></title> </head> <body> <script> function display(){ var i = 10; //局部变量 function fn(){ alert(‘hello’); } return fn; //返回fn函数的首地址 } var test = display(); //定义一个test全局变量,实现display进行引用==>var test =fn; test(); //hello </script> </body> </html>
通过运行可知,以上代码可以正常弹出hello字符串,那么这是不是和我们js的垃圾回收所冲突呢?答:不冲突,原因如下:
当我们把display函数的返回值赋值给全局test全局变量时,相当于把fn的函数的首地址赋值给test全局变量,那么在全局中就会有一个引用关系引用了局部函数fn,当js垃圾回收机制运行时,发现fn函数受到了全局变量的引用,所以并不会回收局部函数fn,所以以上代码可以正常弹出hello字符串。
2、JavaScript中的垃圾回收机制
在内存中有一个引用计数器,如果外部对这块内存有引用,那么引用计数器会自动进行+1操作,当js的垃圾回收机制运行时,如果引用计数器为0,那么会自动回收此内存空间,反之则不清理。
3、闭包的小故事
很久很久以前,有一对姐妹:大桃红、小桃红
小桃红穿越到了清朝,见了传说中四阿哥,又和宫中宫女以及福晋以姐妹相称
有一天:四阿哥问小桃红:“你的姐姐是谁?”,答:“大桃红”
其实闭包也是这样一个概念。
- 闭包即 函数定义时,连同其定义环境的上下文,形成一个整体
- 不管该函数在哪儿运行,其对变量的访问,都要从定义处开始寻找
4、我们眼中的闭包函数
1)函数中的函数
2)把内部函数的首地址作为函数返回值
5、闭包的作用
1)可以在全局作用域中访问局部变量
2)使局部变量一直驻留在计算机的内存中
<!DOCTYPE html> <html> <head> <meta charset=’utf-8′> <title></title> </head> <body> <script> function display(){ var i = 10; function fn(){ alert(++i); } return fn; } var test = display(); test();//11 test();//12 test();//13 test();//14 </script> </body> </html>
注:虽然闭包非常好用且可以让我们访问局部变量,但是不推荐大家使用闭包程序,由于闭包会一直导致局部变量以及闭包不能被JavaScript垃圾回收机制所回收,所以可能会产生内存泄漏,能不用尽量不用,特殊情况除外。