研究下一篇关于js的搞事的文章

之前在知乎上看到了,因为感觉很好玩,所以就手敲了一遍。感谢:

https://zhuanlan.zhihu.com/p/25407758

 

一、实践

1.最简单的循环

毋庸置疑,这里的输出肯定是0到4。

2.加上一个setTimeout延迟执行

变成了这样,会发生什么?:

我的理解:如果这题让我面试,我已经爆炸了。

我当时想到的第一答案是:延迟1s间隔,依次输入0到4。

但是,setTimeout会延迟执行,执行到console.log的时候,其实i已经变成5了。具体过程为:先执行for循环,设定5个间隔一秒延迟方法,这时i就已经++到5了。在执行5个延迟方法的时候,就会输出5个5。

3.那应该怎么改才能输出0到4?

写一个闭包,具体可以参照:

https://zhuanlan.zhihu.com/p/22486908

闭包之后,闭包函数内部的function始终保持对外部变量i的引用。随着i的++,console.log(i)就会输出0到4。

4.如果去掉一个i,会如何?

如果去掉function中的i,那么闭包函数内部的function就没有对外部的i保持引用了。等console.log(i)时,实际上i已经变成了5,所以会输出5个5。

5.如果改成这样,会如何:

这里的:

实际上是一个立即执行函数。那么问题来了,setTimeout可以接受函数或者字符串作为参数,而这里是个立即执行函数,立即执行函数应该等价于undefined。也就是说等价于:

所以setTimeout应该是无效的,function会立刻执行,输出0到4。

6.最后一题的执行顺序主要考察js的运行机制

这里很多东西我都没接触过…所以参照知乎上的解释:

首先先碰到一个setTimeout,于是会先设置一个定时,在定时结束后将传递这个函数放到任务队列里面,因此开始肯定不会输出1。

然后是一个Promise,里面的函数是直接执行的,因此应该直接输出2和3。

然后,Promise的then应当会放到当前tick的最后,但是还是在当前tick中。

因此,应当先输出5,然后再输出4。

最后在到下一个tick,就是1。

所以最后的结果是马上输出23541。

二、总结

这篇文章虽然不长,但是考了很多js的知识点。从起码的预防,到一些关键函数的使用,再到闭包,再到闭包中的一些细节,再到js的运行机制。我到闭包那里就搞不定了。

感觉js的特性还是比较难掌握的。