js闭包和垃圾收集机制
1、JS的回收机制
JavaScript垃圾回收的机制很简单:找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以垃圾回收系统(GC)会按照固定的时间间隔,周期性的执行。
到底哪个变量是没有用的?所以垃圾收集器必须跟踪到底哪个变量没用,对于不再有用的变量打上标记,以备将来收回其内存。用于标记的无用变量的策略可能因实现而有所区别,通常情况下有两种实现方式:标记清除和引用计数。引用计数不太常用,标记清除较为常用。
准确来说,闭包是基于正常的垃圾回收处理机制下的。也就是说,一般情况一个函数(函数作用域)执行完毕,里面声明的变量会全部释放,被垃圾回收器回收。但闭包利用一个技巧,让作用域里面的变量,在函数执行完之后依旧保存没有被垃圾回收处理掉。
可以文字你不太喜欢看,那好,我直接上代码。这可能是很多解说闭包的案列,先拿来用再说
function
foo(x) {
var
tmp = 3;
return
function
(y) {
alert(x + y + (++tmp));
}
}
var
bar = foo(2);
// bar 现在是一个闭包
bar(10);
我们来分析一下这一段代码,在foo中,声明一个变量tmp,他属于foo作用域下的变量。函数返回一个函数,这个函数被嵌套,函数内部弹出x+y(++tmp)。这是个人都看得懂啊,那为什么会出现闭包,怎么出现的了。这接下来就是看执行的过程了,首先执行var bar = foo(2);那么foo就执行了,参数2也传进去了,但是执行完毕之后,tmp变量以及参数x就已经被释放回收了吗?并没有,因为返回值里面还等待使用这些变量咯,所以此时,foo虽然执行了,但是foo的变量并没有被释放,在return在等待继续使用这些变量了,这个时候bar就是一个闭包。
要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
链式作用域,其实就是Javascript的一个特性:子函数中可以访问父函数的所有变量,父对象的所有变量,对子对象都是可见的,反之则不成立。
js code:
var n = 999;
function f1(){
console.log(n);
}
f1(); //999
另一方面,在函数外部自然无法读取函数内的局部变量。
function f1(){
var n = 999;
}
console.log(n); //error
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量。
function f1(){
n = 999;
}
f1();
console.log(n); //999
二、如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
function f1(){
n = 999;
function f2(){
console.log(n); //999
}
}
https://www.cnblogs.com/JIANGCHEN520/p/7118656.html
https://blog.csdn.net/michael8512/article/details/77888000
https://www.cnblogs.com/duanlianjiang/p/5036671.html
https://www.cnblogs.com/duanlianjiang/p/5036671.html