闭包问题详解
一.闭包
特点:
-
- 让外部访问函数内部变量成为可能;
- 局部变量会常驻在内存中;
- 可以避免使用全局变量,防止全局变量污染;
缺点:
-
- 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
应用场景
-
- 实现变量的私有化
- 节流防抖函数等
网上有很多的说法,先不与考虑。官方说法:函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域JavaScript,函数在每次创建时生成闭包。
这边查阅相关资料之后,发现闭包的理解,应该结合执行环境及作用域来分析。首先,我们应当知道,当函数被调用时,会创建一个执行环境(execution context)及相应的作用域链(ps:作用域链本质上是一个指向变量对象的指针列表)。而每个执行环境都有一个 与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。
即,当函数调用时会创建执行环境,作用域链,初始化变量对象
正常情况下,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。 而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
即,当函数调用完毕,执行环境出栈,作用域链会销毁,而与之关联的变量对象也会销毁。
OK,知道以上知识了,我们来看个
简单例子1
function A(){ var age = 10; return function(){ return age; } } var b = A(); b();
当A调用完毕后,按照正常情况,函数执行完毕,变量对象会被销毁。
但是这个例子中,匿名函数引用了A函数中的 age变量,即当A函数执行完毕,因为A函数的变量对象被匿名函数所引用,JS的垃圾回收是引用计数机制。所以A函数的变量对象不会被销毁。只有当匿名函数销毁时,没有了对A函数的变量对象的引用时,A函数的变量对象才会被销毁。
简单例子2
function createFunctions(){ var result = new Array(); for (var i=0; i < 10; i++){ result[i] = function(){ return i; }; } return result; } //result: 10 10 10 ... function createFunctions(){ var result = new Array(); for (var i=0; i < 10; i++){ result[i] = function(num){ return function(){ return num; } }(i); return result; } } //return:1 2 3 ...
这个例子,也是闭包的典型例子,不过它主要是因为函数参数的值传递。由于函数参数是按值传递的,所以就会将变量 i 的当前值复制给参数 num。而在这个 匿名函数内部,又创建并返回了一个访问 num 的闭包。这样一来,result 数组中的每个函数都有自己 num 变量的一个副本,因此就可以返回各自不同的数值了。
本文来自博客园,作者:小L同学,转载请注明原文链接:https://www.cnblogs.com/student007/p/12997062.html