闭包,逆战(疫情)中学习的Lx
- 闭包的概念
闭包(Closure)的概念比较抽象,闭包是能够读取其他函数内部变量的函数。我理解,闭包可以在函数内部定义的函数,继承定义的函数的变量。能够有自己独立的作用域。
2.一个简单的闭包例子
function a(){
var i = 1
function b (){
console.log(i++)
}
return b
}
const c = a()
c()
c()
c()
这个一个简单的闭包,因为函数b使用了函数a的变量,在b的作用域链上有一个变量i,定义后可以有自己单独的作用域,在函数执行完毕后没有被释放,属于b的作用域。
因此执行后在c函数的b自己独立的作用域内的i,因此c执行一次,每次作用域上的i就会+1,自己独立的作用域,因此闭包会造成内存泄露,不被释放,比较耗内存。最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
例如 c函数执行的结果为
c中保存的b使用了a函数中的i,单独作用域,因此没有被释放。当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造 成内存泄露。 内存泄漏就是内存占用,内存被占用的越多,内存就变得越来越少了,就像内存被 泄露了一样 。
3.比较a函数的返回值
function a(){
let i = 1
function b(){
console.log(i++)
}
return b
}
const c = a()
const d = a()
console.log(c === d)
结果为
这个是由于a()执行后返回的函数的地址都是不同的,因此作用域也是独立的。
c()
c()
c()
d()
d()
c调用三次,d调用两次
c和d的执行上下文是不同的,因此,相互之间是不会影响。每次都是独立的执行上下文,同时,由于每次调用都是在上一次的基础上增加,可见函数c的执行完成后还是没有完全被释放,因此会造成内存的泄露。
下面在通个一个例子来进行讲解闭包
function a(){
var b = []
for(var i = 0;i<5;i++){
b[i] = function(){
console.log(i)
}
}
return b
}
c = a()
console.log(c)
c.forEach((item,index) => {
item()
});
该函数已经形成了闭包。变量i的值会跟随函数b保存到外面,因此,c中的内存不会被释放,第一完成后i的值从0一直加到5,指导5不符合条件。当函数c调用的时候,作用域内的i已经变成了5。因此打印结果是5个5。
此处可以利用立即执行函数来解决该问题。
function a(){
var b = []
for(var i = 0;i<5;i++){
(function(i){
b[i] = function(){
console.log(i)
}
}(i))
}
return b
}
c = a()
console.log(c)
c.forEach((item,index) => {
item()
});
由于立即执行函数,每次执行都会生成一个独立的空间来存放i,因此每次执行i分别成0到4被村春进去,档b[i]被执行的时候,就会使用立即执行函数中的i来进行输出。