如何用JavaScript的for循环,原生和ES6写法|按秒依次输出指定数字
如何用JavaScript的for循环,原生和ES6写法|按秒依次输出指定数字
❄️2winter这个问题偶然在群里看见,就把大佬的回答记录下来了。
大佬写了两个一个是旧js的,一个是es6的。
这个是旧版JS的写法,为了构建一个隔离的作用域,防止setTimeout内部访问到全局的i变量,使用了iife函数,增加一个作用域(旧版JS只有函数可以独立作用域)。这样每次压入栈的setTimeout内部使用的i就是实时变化后的i,而不是最后的i。作用域从内层向上层寻找。
1 | (function(){ |
现在我们试试新的let:现在执行是依次输出 0 1 2 按照1s的顺序。
按照顺序入栈,由于函数提升,内部代码会被解析,但是未执行。
也就是说,内部i三次都会传入当前I的值,和上面的例子不同的是,let 声明的i是局部的,每次执行都是一个新的值!
上面的例子存在引用,当最后i变为3的时候,再去执行定时器内部的console引用的是全局变量i所以都是3,而现在这个例子,i不是全局的,当最后入栈的定时器执行时,i依旧是当时传入的i,第一次是0,第二次是1。
这里一定注意:两个例子都是传入了当时的i(0,1,2)。
但是最终执行的时候:
var 的i 是最终变化的为准(存在引用,传入1个旧的i)。
let 的i是每次传入新的i,不是引用先前的,所以,下面的例子输出是传入新的的i(传入3个新的i)。
如果下面代码给成 var 的,会输出3次3,因为函数提升后,最终执行的i是全局变量i,而i已经被改变了。
1 |
|
然后想起来setTimeout有第三个参数,就加上一个:其实目的就一个,让内层的参数与外层分离开。
这个写法也是旧版的,和第一个其实一样的,只是利用了函数的作用域。每次函数入栈,传入i,当开始执行时候,i就不是最外层了,因为内层有一个作用域。就近。
1 | (function(){ |