对闭包的理解

mdn上对闭包的讲解其实很清楚了。
今天看了一下《你不知道的JavaScript》,到闭包那一讲,发现自己之前其实并不是很懂。
闭包,百科上解释是能够读取其他函数内部变量的函数,拿书中的例子来说:

function foo() {
   var a = 2;
   function bar() {
      console.log( a );
   }
return bar;
}
var baz = foo();
baz(); // 2 

按理bar只能在foo函数内部调用执行,foo()调用结束后,根据垃圾回收机制,foo函数应该被清除,但由于闭包的存在,简单来说就是因为函数内部又声明了一个函数,内部函数bar具有对外部函数foo的内部作用域的引用,这个引用的存在就形成了一个闭包,闭包并不是某一个特定的函数或变量,它是一个形式,一种设计原则。

作用域链的存在,使得函数内部可以访问外部的变量;
闭包的存在,使得函数外部也能访问函数内部的变量。

比较经典的闭包是for循环闭包:

for (var i=1; i<=5; i++) {
   setTimeout( function timer() {
   console.log( i );
   }, i*1000 );
}

即使setTimeout最后的参数为0,执行里面的函数时,取值i的时候会从上级寻找,这个时候for循环执行完,i变为了6。
本来是想让每次循环输入顺序数,但没有达到想要的效 果,因为每次循环都相当于声明了一个相同的函数,等到最后依次执行时,最后的函数覆盖了之前的,因为这一点就都会输出6,因此解决的一个方法就是创建一个闭包
dede
加上一层闭包立即执行函数以后,function里面变量i每次都能从外层找到传入的i,而这个i每次循环的时候都传进去了
另外一种方法是将for中的var改为let,解释起来是JavaScript引擎循环过程中能够记住上一轮的值。每一次的let都形成了一个块级作用域,如下:

let i=0;
function(){
	console.log(i)
}

由于let是块级作用域,大括号将i绑定在里面,每次往上寻找都能记住,所以结果会依次输出。

注:循环引用的问题可以用 标记清除 来解决
在这里插入图片描述
图片来自:https://juejin.im/post/5d0706a6f265da1bc23f77a9#heading-9
垃圾收集器运行时将所有的元素都标记,从根部出发将能触及到的变量进行清除,未被清除的变量将被回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值