闭包:
闭包是js中的一种独特机制,它本质上是一个函数,在这个函数 中可以引用外部函数的变量,且这些变量不会在函数调用完成后被立即销毁。
要想完全了解js中的闭包就需要去搞懂【作用域、作用域链、垃圾回收机制】
作用域
js中作用域分为全局作用域和块级作用域,全局作用域下的变量和方法能够在任何地方被访问到,而块级作用域却之内在其当前或内部作用域中被访问
全局作用域特点
-
全局作用域在页面打开的时候被创建,页面关闭时候被销毁
-
编写在script标签中的变量和函数作用域为全局,页面任意位置可访问
-
全局作用域中有个全局对象window,代表一个浏览器窗口,由浏览器创建,可直接调用
-
全局作用域中的变量和函数作为window的属性和方法保存
函数作用域特点
-
函数调用的时候,函数作用域被创建,函数执行完毕的时候被销毁
-
每次调用函数都会创建一个新的函数作用域,它们相互独立
-
在函数作用域中可以访问到外层作用域的变量,遵循就近原则获取变量值;外层作用域无法访问内层的变量
作用域链
在js中,当你要访问一个变量或方法时,首先会在当前作用域下查找,如果当前作用域下没有查找到该变量或方法,则返回上一级作用域进行查找,直到找到全局作用域,这个查找过程形成的链条叫做作用域链。
JavaScript垃圾回收机制
-
引用法:就是判断一个对象、变量的被引用数,引用数
为0
就回收,引用数大于0
就不回收,js不会去清除正在被使用的变量。 -
标记法:标记法就是,将
可达
的对象标记起来,不可达
的对象当成垃圾回收。什么 是可达呢?就是从初始的根对象window
的指针开始,向下搜索子节点,子节点被搜索到了,说明该子节点的引用对象可达,并为其进行标记,然后接着递归搜索,直到所有子节点被遍历结束。那么没有被遍历到节点,也就没有被标记,也就会被当成没有被任何地方引用,就可以证明这是一个需要被释放内存的对象,可以被垃圾回收器回收。
闭包原理
闭包原理本质上就是利用了js作用域链特性
function sum() {
let a = 1;
return function () {
console.log(++a)//此处引用了外部函数sum中的变量 a ,故a会被一直保存在内存中
}
}
let sum1 = sum()
sum1()//2 //变量a被延续使用
sum1()//3
sum1()//4
闭包的应用
- 防抖
- 节流
- 单例模式
- Vue中的data()函数