闭包介绍参考: https://blog.csdn.net/vuturn/article/details/44560717 (里面有介绍闭包会出现的内存泄漏问题,以及解决办法)
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
看两个例子:
例1:
var fo = (function (){ var a = 99; return function(){ return a; } })(); console.log(fo);
例2:
var foo = ( function() { var secret = 'secret'; // “闭包”内的函数可以访问 secret 变量,而 secret 变量对于外部却是隐藏的 return { get_secret: function () { // 通过定义的接口来访问 secret return secret; }, new_secret: function (new_secret) { // 通过定义的接口来修改 secret secret = new_secret; } }; }()); foo.get_secret (); // 得到 'secret' foo.secret; // Type error,访问不能 foo.new_secret ('a new secret'); // 通过函数接口,我们访问并修改了 secret 变量 foo.get_secret (); // 得到 'a new secret'
1、内嵌函数:一个函数内部还有函数,就是内嵌函数。(重点:内嵌函数 不一定是闭包函数,闭包一定有内嵌函数在return后面)
2、闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。(注:由于js的垃圾回收机制,函数在执行结束,内部声明的变量都会清除,但是闭包不会清除,仍然存在内存中,所以内存消耗很大,不能滥用闭包)
3、通常,一个函数(暂记为 makeAdder
)执行到 return后,JavaScript 的垃圾回收器会在这时回收 函数 创建的作用域对象(暂记为 b
)。但是闭包中 return 后 的函数(暂记为 adder
)里面的变量,拥有一个指向作用域对象 b
的引用,
最终,作用域对象 b
不会被垃圾回收器回收,直到没有任何引用指向函数 adder。
个人理解:return 后的函数没有指向 作用域对象 b
的引用 或 return 后根本没有函数 就不叫闭包。
(return 的值 只是一个普通对象,引用的值会马上赋值给这个对象,不会再指向作用域对象 b
。函数内的引用,只有执行函数时,才能获取这个变量的值。所以闭包函数中有指向作用域对象 b
的变量,执行完makeAdder函数,还不能被回收)
4、 闭包突破了"链式作用域"结构规则,在外部通过接口还是可以访问到内部的变量。
5、如果外部需要函数内的一个变量,则直接返回函数就可以,如例1所示;如果需要访问内部多个变量则返回必须是一个对象,如例2所示。
总结:闭包的一个明显的特点,一定有return,且return中一定有函数(直接函数 或 对象中有函数)。
闭包内存泄漏问题:(内存空间没有指针指向就会回收,出现循环引用才会导致内存泄露)
https://www.cnblogs.com/greatluoluo/p/5930685.html
如上面链接中例子:
function leakMemory() { var el = document.getElementById('el'); var obj= { 'el': el }; el.obj= obj; }
这段代码中(还不是闭包函数),函数中引用了外部的dom对象,同时, 函数中的 el.obj 给外部的dom对象添加了一个属性,引用了函数内的obj对象。
这样就存在了相互引用的问题,js垃圾回收机制无法回收这个函数。
function addHandler() { var el = document.getElementById('el'); el.onclick = function() { el.style.backgroundColor = 'red'; } }
我们常常像这个例子中一样,在函数中给DOM对象创建事件,这样无意识中就存在内存泄漏问题。(个人觉得解决内存泄漏问题,可以把变量使用后设置为 null ,断开引用)
https://www.cnblogs.com/yakun/p/3932026.html
https://blog.csdn.net/johnny0991/article/details/51778436 (能导致内存泄漏的一定是引用类型的变量,而值类型的变量是不存在内存泄漏的)