-
什么是闭包?个人理解
个人觉得闭包没有那么复杂,本质就是上级作用域内变量的生命周期,因为被下级作用域内引用,而没有被释放。就导致上级作用域内的变量,等到下级作用域执行完以后才正常得到释放。
-
闭包是怎么形成的?
我认为比较容易理解的闭包定义:函数嵌套函数时,内层函数引用了外层函数作用域下的变量,并且内层函数在全局环境下可访问,进而形成闭包。
看以下简单的示例:
function numGenerator(){
let num = 1
num++
return () => {
console.log(num)
}
}
var getNum = numGenerator()
getNum()
在这个简单的闭包示例中,numGenerator创建了一个变量num,接着返回打印num值得匿名函数这个函数引用了变量num,使得外部可以通过调用getNum 方法访问变量num,因此在numGenerator执行完毕后,即相关调用栈出栈后,变量num不会消失。仍然有机会被外界访问。
f12查看Chrome devtool可以看到 num被标记为Closure,即闭包变量。
image.png-
闭包基本原理
我们知道在正常情况下外界是无法访问函数内部变量的,函数执行之后,上下文即被销毁。但是在函数(外层)中,如果我们返回了另一个函数,且这个返回的函数使用了函数(外层)内的变量,那么外界便能够通过这个返回的函数获取原函数(外层)内部变量值,这就是闭包基本原理。
下面来看几个例子
例题1:
const foo = (function (){
var v= 0
return () =>{
return v++
}
}())
for(let i = 0; i< 10; i++){
foo()
}
console.log(foo());
上面代码输出的答案是10
。分析一下这道题,
foo是一个立即执行函数,调用的时候他要先执行如下代码:
function (){
var v= 0
return () =>{
return v++
}
}()
此时形成的闭包v已经加了1 已经为1,后面再调用十次,从1开始累加10次,答案是10
例题2:
const foo = () => {
var arr = []
var i
for(i=0; i< 10; i++){
arr[i]= function(){
console.log(i)
}
}
return arr [0]
}
foo()()
答案:10. 因为自由变量i,类似例题1,执行foo返回的是arr[0],arr[0]此时是函数。但是自由变量已经执行了10次,变成了10,所以再调用arr[0]里面的函数就会打印10
例题3:
var fn = null
const foo = () =>{
var a = 2
function innerFoo(){
console.log(a)
}
fn = innerFoo
}
const bar = () =>{
fn()
}
foo()
bar()
答案为2.
正常来讲,foo函数执行完毕后,其执行环境生命周期会结束,所占用的内存会被垃圾收集器释放,上下文消失、但是通过innerFoo函数赋值了给全局变量fn,foo的变量对象a就会保留下来。这就跟例题1中 return () =>{ return v }
返回了变量一样。然后被引用。所以依然可以访问到这个被保留下来的对象。
-
闭包的作用
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
网友评论