JS闭包是一个绕不过去的知识点,这里主要是为了记一下闭包相关的知识点,以及闭包的简单实现和原理
1.作用域、作用域链
参照《JS高级程序设计》这本书中(PS:对比了一下犀牛书与这本书的关于闭包的解释,个人觉得JS高程的阐述更加容易理解,不喜勿喷):
<--
“执行环境”是JS中最为重要的一个概念,执行环境定义了变量或函数有权访问其他的数据,决定了各自的行为,每个执行环境都有与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中,虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。
全局执行环境是最外围的一个执行环境,在Web浏览器中全局环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁
每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入环境栈中,而在每个环境执行完毕后,栈将其环境弹出,把控制权交给之前的环境。
当代码在一个环境中执行时,会创建变量对象的一个作用域链,作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
-->
因此,在第二个知识点关于垃圾回收机制也可以简单理解为,不能被访问到的变量或对象就会被垃圾回收机制自动清理
2.垃圾回收机制
垃圾回收机制一般有两种:
a.标记清除
当进入环境(上述)时。就标记为“进入环境",离开环境,就标记为”离开环境”,标记的策略可以用任何方式去实现
<--
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记,而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了
-->
b.引用计数
<--
另一种不太常见的垃圾收集策略叫做引用计数,引用计数的含义是跟踪记录每个值被引用的次数,当声明了一个变量并将一个引用类型复制给该变量时,则这个值的引用次数就是1,如果同一个值又被赋给另一个变量,则该引用次数加1,相反,如果包含对这个值引用变量又取得了另外一个值,则这个值的引用次数减1,当引用次数为零,则说明无法访问,,因此可以回收其空间
-->
但是这种方式存在一个问题就是:循环引用
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
//在这个例子中objectA与objectB的引用次数永远都不可能是0.
在学习垃圾回收的过程中,看到了一篇通俗易懂的技术贴,个人觉得写得非常好,在此附上链接:
https://segmentfault.com/a/1190000018605776?utm_source=tag-newest
-------------------------------------------------------------分割线---------------------------------------------------------------
看一个简单的例子:
function f1() {
var n = 101;
function f2() {
console.log(n);
}
return f2;
}
var num = f1();
num(); //101
我们定义一个函数 f1 ,这个函数处在全局作用域中,在 f1 的内部定义一个变量 n ,由于js作用域链的单向问题,能从内部访问外部,但是不能从外部访问内部的原则,我们在全局环境中是无法获取 变量n的值的。
但是如果定义一个匿名函数,并且将其返回,那么我们在全局作用域中接收这个函数就可以访问 n 的值了,这就是闭包的一个简单使用
闭包的使用场景还有诸如:
解决 setTimeout 不能传参的问题、封装私有变量等等
此类文章数不胜数,在此不做赘述,
比如:https://www.cnblogs.com/gg-qq/p/11399152.html 这篇技术贴就总结的还不错,推荐!
(如有理解错误,恳请指正)
本文深入探讨JavaScript中的闭包概念,包括作用域、作用域链及闭包的实现原理。同时,讲解了垃圾回收机制的两种策略:标记清除与引用计数,以及闭包在实际开发中的应用。
248

被折叠的 条评论
为什么被折叠?



