JS闭包
相关要点
-
内存泄漏
过多的占用系统内存的行为,相当于攥着一团湿毛巾,流失的水越多,剩余的水越少,相当于内存剩余越少。
-
何为功能
一个真正的功能不应该依赖于外部的东西,自己本身就应该能独立完成这个事儿,这样的功能才是一个真正完整的功能。
例:
//一个简易累加器 var count = 0; function test(){ count ++; console.log(count); } test(); test(); test(); //输出 1 2 3 //该功能依赖于外部的全局变量,并非自身完成,闭包的方法见下
-
只有表达式才能被执行
闭包理解
-
当内部函数被保存到外部时将会产生闭包,闭包会导致原有作用域链不被释放(因为闭包函数拿着外部函数的执行成果,导致外部函数作用域链无法释放),造成内存泄漏。
-
内部函数保存到外部函数的俩个简单方法( 还有更牛批的, but菜鸟的我还不会 ):
-
return
<script> function a() { function b() { console.log(tt); } var tt = 9; return b; } var demo = a(); demo(); </script>
-
传值给全局变量
<script> var demo function a() { var tt = 9; function b() { console.log(tt); } demo = b; } a(); demo(); </script>
-
-
闭包的特点:
- 闭包函数里能访问到其外部函数的局部变量
- 闭包函数能延长其外部局部变量的生命周期, 使其一直存在
- 模块化开发时,不会互相污染变量
- 当多个函数同时和一个函数形成闭包时,他们的变量是可以共用的,因为同属于一个域,类似缓存结构,例如闭包用法的例子
闭包的一些用法
-
实现公有变量
//函数累加器 <script> function add() { var num = 0; function scr() { console.log(++num); } return scr; } var demo = add(); demo(); </script>
-
可以做类似缓存的事情 (存储结构)
<script> function test() { var ani = "dog"; var obj = { terani : function () { if(ani != ""){ console.log("this is " + ani); ani = ""; }else{ console.log("empty!"); } }, pushani : function (newani) { ani = newani; } } return obj; } var animation = test(); animation.terani(); animation.terani(); animation.pushani("lion"); animation.terani(); </script> //输出结果 this is dog empty! this is lion
-
可以实现封装,属性私有化
-
模块化开发,防止污染全局变量
闭包编程常见坑
-
函数的执行顺序并非视觉上的顺序,函数只有在调用时才执行,在它未执行时,函数中的值是随着执行语句前的行为在变的。
//简单例子 num = 100; function test(){ console.log(num); } num = 200; test(); //输出 num = 200; //复杂例子 function test() { var arr = []; for (var i = 0; i < 10; i++) { arr[i] = function () { console.log(i); } } return arr; } var myarr = test(); for (var j = 0; j < 10; j++) { myarr[j](); } //输出 10 个 10 //解决这个问题,让他正常输出 //利用立即执行函数,形成1对1的形式 function test() { var arr = []; for (var i = 0; i < 10; i++) { (function (j) { arr[j] = function () { console.log(j); } } (i)) } return arr; } var myarr = test(); for (var j = 0; j < 10; j++) { myarr[j](); }
闭包面试坑
-
使用原生js,addEventListener,给每个li元素绑定一个click事件,输出他们的顺序
<ul> <li>a</li> <li>a</li> <li>a</li> <li>a</li> </ul>
错误写法:
//闭包问题,导致输出全为4 function test() { var liCollection = document.getElementsByTagName("li"); for (var i = 0; i < liCollection.length; i++){ liCollection[i].onclick = function () { console.log(i); } } }; test();
正确写法:
//使用立即执行函数,形成一对一的形式 function test() { var liCollection = document.getElementsByTagName("li"); for (var i = 0; i < liCollection.length; i++){ (function (j) { liCollection[j].onclick = function () { console.log(j); } }(i)) } }; test();