闭包一直是一个js学习过程中的难点,先后看了几次,还是没能完全体会。
现从为什么需要闭包,闭包的解决的问题以及原理,以及闭包怎么使用和注意事项开始梳理:
为什么需要闭包
首先,根据js的作用域链:内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量。但是没有外部作用域下获取内部作用域下变量和在不同函数作用域中互相访问变量的途径。那么当有上序需求的时候(如游戏中人物角色的复活次数,不能暴漏出来让其他部分都能修改,但又要让其他函数获取),就需要使用闭包。
闭包的原理
闭包之所以能访问其外层函数作用域中的变量,是因为闭包的(内部函数)作用域链中存在外层函数的变量对象。即使外层函数执行结束,但由于其变量对象仍然被内层函数的作用域引用,因此不会被内存回收,直到闭包执行结束后,外层函数的变量对象才会被回收。
举例:
function outerFn(){
var num = 10; //num变量被内部函数所引用,不回收
function innerFn(){
var i = 0; //局部变量没有再被谁引用,用完就回收
console.log(++i);
console.log(++num);
}
return innerFn;
}
var inner = outerFn();
inner() //1 11
inner() //1 12
闭包的解决变量缓存的问题
闭包解决了数据缓存的问题。可以根据上序例子中可以看到。
可能大家和我有一样的疑惑 ,把变量提升为全局变量也可以起到缓存值作用。
闭包和 把num提升到全局变量做缓存还是有不同的,例子如下:
var num = 10;
function outerFn(){
console.log(++num);
}
outerFn(); //11
outerFn(); //12
这样也像是缓存num的值,但这里和闭包有不同:
num不再是一个局部变量了( 而闭包中只有用innerFn 才可以修改)没有起到保护作用,任何地方修改了这个值 num的值都会变化(体现它全局的特性)
举个例子:点赞功能(点击对应下面的按钮,点赞数目+1)
这时候每个图片下面的赞的数目不能设置为全局变量但又要求缓存,这时候使用闭包 解决。
闭包的使用和注意事项
闭包通常都是用函数嵌套函数+返回函数的形式使用(像上序的例子)
函数嵌套函数 是因为需要局部变量;
返回函数 是因为如果不return,就无法使用这个闭包。
注意事项:
若闭包在外层函数执行结束后执行,那么它只能获取到外层函数中所有变量的最终状态。
参考的博客:
https://www.cnblogs.com/jesse131/p/9079290.html