1.闭包(Closure)
1.1 是什么?
并没有标准答案。介绍个非标准答案作为参考。
非标答案1:“闭包就是能够读取其他函数内部变量的函数”
个人理解(出处忘记了):闭包就是指一个作用域有权访问另一个作用域中的局部变量,本质仍是函数。
最常见的闭包:嵌套的函数中,子函数可以使用父函数中的变量。父无法使用子函数的变量,改变子函数中的变量,父函数中的变量不会变
以一段代码展示闭包:(从代码形式上看闭包是一个做为返回值的函数)
<script> function foo() { let i = 0; // 函数内部分函数 function bar() { console.log(++i); } // 将函数做为返回值 return bar; } // fn 即为闭包函数 let fn = foo(); fn(); // 1 </script>
1.2 作用?
1.闭包能够创建外部可访问的隔离作用域,避免全局变量污染
举个例子:嵌套的两个函数,父函数定义a=2,子函数将a改成1,那么再两个函数中分别打印的话,分别是2 和 1 ,原因就是闭包(当然根本原因是函数作用域,就是每个作用域都是独立的)
2.延长变量的使用范围
1.3 缺点?
过度使用可能导致内存泄漏
1.4 实际中的使用
实际工作中,经常写出闭包,换言之,在日常开发中,闭包可谓“”无处不在“”
2.内存泄漏
2.1 是什么?
说法一:内存泄漏指任何对象在您不再拥有或需要它之后仍然存在
说法二:指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束。
正常情况下,js的垃圾回收机制,会清理变量和函数,什么时候清理呢?就是这个变量或者函数,除了你定义时,其他时候不使用它了,就会被垃圾回收机制回收。
2.2 引起内存泄漏的原因和解决方法
1、意外的全局变量引起的内存泄漏
原因:全局变量,不会被回收。
解决:使用严格模式避免
2、闭包引起的内存泄漏
原因:闭包可以维持函数内局部变量,使其得不到释放。
解决:将事件处理函数定义在外部,接触闭包,或者在定义事件处理函数的外部函数中,删除对DOM的引用。
3、没有清理的DOM元素引用
原因:虽然别的地方删除了,但是对象中还存在DOM的引用。
解决:手动删除
4、被遗忘的定时器或者回调
原因:定时器中有DOM的引用,即使DOM删除了,但是定时器还在,所以内存中还是有这个DOM。
解决:手动删除定时器和DOM
5、子元素存在引用引起的内存泄漏
原因:p中的ul li 得到这个p,会间接引用某个得到的li,那么此时因为p间接引用li,即使li被清空,也还在内存中,并且只要li不被删除,它的父元素都不会被删除。
解决:手动删除情空
3.作用域链
3.1 是什么?
作用域连成的链状结构,提供变量的查找机制
3.2 特点
- 相同作用域链中按着从小到大的规则查找变量
- 子作用域能够访问父作用域,父级作用域无法访问子级作用域(就近原则)
- 外部无法访问内部的变量
3.3 作用
延长变量的使用范围(可以用父级,乃至祖宗级的变量)
避免变量污染(外部无法访问函数作用域,就近原则)
提供变量的查找机制
关于闭包和作用域的区别还没有一个完整的答案,感觉他们俩在很多方面是共通的,等以后再来填坑吧。