闭包的经典面试题之一

闭包的经典面试题之一

首先,上题目:

问打印结果是什么?在这里插入图片描述
结果为:
在这里插入图片描述
要做这道题,首先要理解以下概念:
1.js的执行机制:单线程执行,也就是所谓的stack(栈).
2.作用域链:可以看作一个集合,即当前作用域及父级的作用域的集合。

可以看下图一个函数的执行过程:
首先进行全局执行上下文,执行完毕后,根据上下文存在的books函数,就去执行books的执行上下文,再然后是匿名函数的上下文在这里插入图片描述

在这里还需要再了解一下执行机制,由于js是单线程执行机制,在执行上下文的时候,若是出现了一个方法中的事情很多,每次都需要等待该方法执行完毕再执行下文,那就会出现很大的问题,所以这个时候就出现了任务队列机制
例如setTimeout的执行过程,js执行不可能等待setTimeout里面的代码执行完毕再接着执行下文,毕竟它有个等待时间,假设这个时间很长呢?会造成下面的代码全部停止执行,所以这个任务队列执行机制是很有意义的。
接着面试题来说,只要用了setTimeout方法,即使里面的毫秒数为0,里面的函数不会立即放到执行栈中去,而是由浏览器先进行处理,得到的结果放到任务队列中,等待执行栈执行完毕之后,再根据setTimeout的时间间隔放到执行栈中,也就是说,这里的任务队列有浏览器先处理的5个i++,因为并未实际执行(因为全局执行上下文还没有完成,没有i值),所以这里没有计算结果,即相当于‘还在加工中,未完成产品’
在这里插入图片描述
根据if循环的执行顺序(要注意一下,忘记的可以去补),最后的打印i,来自for循环完成后的i=5;
然后,执行上下文完毕了,任务队列放到执行栈中,此时的已经是5,所以会间隔4000ms后,一下子打印出5,6,7,8,9
但是这里也要格外注意两点:
1.这个console.log(i++),如i=5,所以会从5开始打印,而不是6;而有五次任务,所以依次打印出以上结果。
2.这个setTimeout方法虽说间隔4000ms,但是是在执行上下文完毕之后的间隔,全局执行上下文也需要时间,所以是很大可能是大于4000ms的;而且在这里是4000ms后一下子打印出来,而不是4000ms打印一个数字。

在这里插入图片描述
在这里插入图片描述

那么考核重点来了,如何改代码才能打印出0,1,2,3,4呢?
答案:
在这里插入图片描述
为什么这样改呢,首先需要看懂代码。
在这里再普及以下匿名函数和立即执行函数的区别
匿名函数:即没有名字的函数,匿名函数不能直接使用,只有在属性、方法、对象等有依赖时才可以使用
在这里插入图片描述
立即执行函数(也叫自执行函数):
首先什么叫自执行:我们定义一个函数,并且立即执行它即为自执行。
由于外部访问不到其内部的变量,因此执行完之后立即被释放,不会玷污到全局对象。自执行,即创建和调用为一体。
在这里插入图片描述
常见的立即执行函数方式,(推荐第一种写法,阅读性更强,但是第二种用用的人也比较多)
在这里插入图片描述
首先,全局执行上下文,从上到下,执行过程是这样的:
此时第一次循环,i=0,但是这里由于有一个立即执行函数,所以传入一个参数i=0,然后x=i=0,此时遇到setTimeout,所以交给浏览器处理,此时x=0,所以任务队列中有数值0。
在这里插入图片描述
上面的函数执行栈执行完后从栈中弹出,回到全局执行上下文。
在这里插入图片描述
然后进行第二次循环,此时的i=1,通过立即执行函数传入x=i=1,然后setTimeout,交给浏览器处理…和第一次一样,然后任务队列中加入数值1.
在这里插入图片描述
然后再弹出,再立即执行函数…以此循环,
在这里插入图片描述
然后这里循环执行完毕了,i=5结束循环,然后到下面的console.log(i),毫无疑问结果是5;
然后到这里全局执行上下文的代码已经没有了,所以会执行任务队列里面的代码,也就是将数值01234输出来,
在这里插入图片描述
后续:接着看下面几个循环的执行区别
图一:
在这里插入图片描述
图一的执行过程:全局执行上下文开始,但是遇到setTimeout所以放到任务队列中,所以任务队列中是未开始计算的5个i++。
在这里插入图片描述
然后循环完毕后i=0,任务队列里面的代码开始执行到执行栈,即i++开始计算,所以打印出0,1,2,3,4

图二:
在这里插入图片描述

和图一的区别是:任务队列里是5个i。

文中引用了多处博客和视频教程,且写的有任何错误欢迎指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值