先看一段代码:
<script type="text/javascript">
...
function outer () {
let a = 123;
function inner () {
console.log(a);
}
inner();
}
outer();
let bb = 1;
...
</script>
这段代码执行完outer(),理论上outer函数作用域下的内存就销毁了,再也不存在了,所以outer函数作用域内的变量再也访问不了。
(严格来说,当函数运行到这段代码块结尾后,对应的执行上下文被弹出 stack 执行栈,等待引擎回收器回收分配出去的内存)
但outer函数并不会被销毁(因为这段代码中outer函数属于全局上下文,只要全局上下文没销毁,全局上下文里面的变量是不会被销毁的),所以还是可以再次执行outer函数的,再次调用的时候,outer函数所有变量回到初始状态(代码重新跑一遍)
如果修改一下代码:
function outer () {
let a = 123;
let b = {a: a}
function inner () {
console.log(a);
}
return inner;
}
var ob = outer();
let bb = 1;
...
执行完outer函数后,给全局作用域下的ob赋值inner函数,由于script下的代码属于全局作用域,在页面销毁之前,全局作用域下的变量是不会销毁的,所以即便所有代码执行完毕,ob也不会被销毁,从而被引用inner函数也不会被销毁,所以outer函数作用域也不能销毁,这样,回收机制就无法回收outer函数作用域分配出去的内存,导致内存泄漏。
上面的那种情况ob就是闭包,但如果outer函数return b 对象,你就不能说对象b形成了一个闭包。
JavaScript中的函数才会形成闭包。 闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。
那闭包内存溢出的问题怎么可以解决? 用完ob之后,设置ob = null 这样就可以了。
复杂的版本:
https://www.jianshu.com/p/0aed3c135a1c
https://www.jianshu.com/p/f58c030182b4