| 「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」 |
|---|
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。
闭包有两个常用的用途。
-
闭包的第一个用途是使我们在
函数外部能够访问到函数内部的变量。通过使用闭包,我们可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。 -
函数的另一个用途是
使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。
其实闭包的本质就是作用域链的一个特殊的应用,只要了解了作用域链的创建过程,就能够理解闭包的实现原理。
使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念
闭包有三个特性:
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被F垃圾回收机制回收
- 作用域和自由变量
- 自由变量查找:在函数定义的地方(而非执行的地方)
- 闭包应用场景
- 作为参数被传入
- 作为返回值被返回
- 闭包的影响
- 变量会常驻内存,得不到释放
// 自由变量示例 -- 内存会被释放
let a =0
function fn1(){
let a1 =100
function fn2(){
let a2= 200
function fn3(){
let a3 = 300
return a +a1+a2+a3
}
fn3()
}
fn2()
}
fn1()
// 闭包 函数作为返回值--内存不会被释放
function create(){
let a =100 //被下面函数引用,不能释放
return function(){
console.log(a)
}
}
let fn =create()
let a =200 //没被引用,可被释放
fn() // 100
// 闭包 函数作为传入值--内存不会被释放
function print(fn){
let a =200 //没被引用,执行完成就可释放
fn()
}
let a =100 // 被fn引用,不能释放
function fn(){
console.log(a)
}
print(fn) // 100
常见闭包使用场景
间隔1s打印1-5
for (var i=1; i<=5; i++) {
//闭包
(function (i) {
setTimeout(() => console.log(i), 1000*i)
})(i)
}