前端Javascript笔试题收录----Event loop和闭包

上周面试中遇到一道考察闭包和Event loop的题目。交卷后面试官还问我觉得难么,我说闭包这道挺绕的。回家后自己执行了一遍,通过查阅书籍和在不同位置打印之后,有了一些思考。在这里记录一下,希望能和大家交流分享。

var a = 0, b=0, c=0;
for (var i = 1;i <= 3; i++) {
	var i2 = i;
	(function() {
		var i3 = i;
		setTimeout(function() {
			a += i;
			b += i2;
			c += i3;
		}, 1)
	})();
}

setTimeout(function() {
	console.log(a, b, c);
}, 100)

答案:12 9 6

流程大概是这样:
1.全局域中声明了三个变量:a、b和c。
2.for循环中依次将i赋值给i2。
3.for循环中执行了一个匿名函数,函数体中将i值赋值给i3。
4.匿名函数中还定义了一个计时器,分别将i、i2和i3累加给a、b和c。
5.最后在另一个计时器中打印a、b和c。

Event loop

因为JS中的运行机制是单线程,而遇到诸如事件、计时器或者Promise这种异步事件,JS会将其挂起到一个事件队列中。异步事件挂起后,JS代码会继续向下先执行同步的事件,当所有同步事件执行完毕后,再回来按顺序执行异步队列中的任务。

所以当匿名函数中的计时器执行时,for循环已经结束,i和i2每次累加的值都是4和3 。网上也有很多JS运行机制的帖子和题目。

那么最终a=12,b=9的答案就很明显了。最后就是为什么c的值是6呢?

闭包
《Javascript忍者秘籍》中对于闭包的概念是这样阐述的:

闭包允许函数访问并操作函数外部的变量。 只要变量或函数存在于声明函数时的作用域内,闭包即可使函数能够访问这些变量或函数。

还有一句:

这就是闭包。闭包创建了被定义时的作用域内的变量和函数的安全气泡,因此函数获得了执行时所需的内容。该气泡与函数本身一起包含了函数和变量。

按照这个说法,变量i3的声明和计时器内的函数声明在同一个作用域,可以保证每次计时器中的函数执行时,都能获得当时保存的i3变量,也就是for循环依次递增的i值:1,2,3 。

最后还试了一下,for循环中如果使用let声明变量i,同样可以实现每次for循环都能访问正确的i值的效果。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值