^finished
1. 闭包作用
避免变量全局污染
使数据私有化,外部无法修改内部的数据
可以让外部使用内部的私有数据
以上这些作用,函数也可以实现
开始之前,你需要了解函数的基本使用以及作用域链。
2. 闭包的核心作用
- 使变量可以驻留在内存,不被回收(普通函数不具备) 用代码来解释,写一个让变量
a自增的函数。
js
let a = 10 // 全局变量,容易被污染
function fn() {
a++
console.log(a)
}
fn() // 11
fn() // 12
fn() // 13let a = 10 // 全局变量,容易被污染
function fn() {
a++
console.log(a)
}
fn() // 11
fn() // 12
fn() // 13几个人同时开发,对变量 a 污染,或者你自己忘记了又对变量 a 赋值了。
js
let a = 10 // 全局变量,容易被污染
···
a = 100 // 其他开发成员又对a进行赋值了(污染)
···
function fn() {
a++
console.log(a)
}
fn() // 101
fn() // 102
fn() // 103 被污染了let a = 10 // 全局变量,容易被污染
···
a = 100 // 其他开发成员又对a进行赋值了(污染)
···
function fn() {
a++
console.log(a)
}
fn() // 101
fn() // 102
fn() // 103 被污染了把这个变量写在函数的里面,那么 a 就不会被污染了。但是每次自增都重新从10开始。
js
function fn() {
let a = 10 // 局部私有变量
a++
console.log(a)
}
fn() // 11
fn() // 11
fn() // 11function fn() {
let a = 10 // 局部私有变量
a++
console.log(a)
}
fn() // 11
fn() // 11
fn() // 11怎么样让变量 a 长期驻留在内存?这时候就要用到闭包了。
闭包
只要在之前的函数里面再嵌套一个函数,把自增的代码放进去。仅需注意两点:
- 函数里面嵌套一个函数
- 里面的函数要使用到外层函数的变量,如果没有使用到,那么是不会形成闭包的。
我们需要执行变量 a 自增的操作,将内部函数 return 出去即可。
js
function fn() {
let a = 10 // 局部私有变量
function () {
a++
console.log(a)
}
}function fn() {
let a = 10 // 局部私有变量
function () {
a++
console.log(a)
}
}以上现在只是将闭包的形式写出,现在要把闭包创建出来,执行外部函数 fn() 即可。
js
function fn() {
let a = 10
return function () {
a++
console.log(a)
}
}
fn() // 创建一个闭包,仅需执行一次fn()function fn() {
let a = 10
return function () {
a++
console.log(a)
}
}
fn() // 创建一个闭包,仅需执行一次fn()用变量 f 将 fn() 的执行存起来。
js
function fn() {
let a = 10
return function () {
a++
console.log(a)
}
}
let f = fn() // 创建闭包,可以通过断点在控制台看到
// 执行3次f
f() // 11
f() // 12
f() // 13function fn() {
let a = 10
return function () {
a++
console.log(a)
}
}
let f = fn() // 创建闭包,可以通过断点在控制台看到
// 执行3次f
f() // 11
f() // 12
f() // 13后面每次都是执行 f() 这个函数(内部函数)而不是 fn() ,外部 fn() 这个函数只是一开始创建闭包的时候执行了一次 ,a = 10 这句只会执行一次。
内存泄露
闭包里面的变量是不会被释放的,所以每次自增都会驻留下来。
双刃剑
闭包可以让变量驻留在内存,不被回收。
处理不当可能造成内存泄露,可以手动清除。
js
function fn() {
let a = 10
return function () {
a++
console.log(a)
}
}
let f = fn()
f()
f()
f()
f = null //手动清除function fn() {
let a = 10
return function () {
a++
console.log(a)
}
}
let f = fn()
f()
f()
f()
f = null //手动清除也并不是所有的闭包都需要清除,有一些内存泄露的情况是可以允许的。
liang14658fox