如何用JavaScript的for循环,原生和ES6写法|按秒依次输出指定数字

这个问题偶然在群里看见,就把大佬的回答记录下来了。

大佬写了两个一个是旧js的,一个是es6的。

这个是旧版JS的写法,为了构建一个隔离的作用域,防止setTimeout内部访问到全局的i变量,使用了iife函数,增加一个作用域(旧版JS只有函数可以独立作用域)。这样每次压入栈的setTimeout内部使用的i就是实时变化后的i,而不是最后的i。作用域从内层向上层寻找。

(function(){
 for (var i = 0; i < 3; i++) {
 	
 	(function(ii){
 		setTimeout(
 			function(){
 				console.log(ii);
 			},1000*ii);
 	})(i)
 }
})();

现在我们试试新的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已经被改变了。


(function(){
 for (let i = 0; i < 3; i++) {
 		console.log("out:" + i);
 		setTimeout(
 			function(){
 				console.log(i);
 			},1000*i);	
 		
 }
})();

然后想起来setTimeout有第三个参数,就加上一个:其实目的就一个,让内层的参数与外层分离开。

这个写法也是旧版的,和第一个其实一样的,只是利用了函数的作用域。每次函数入栈,传入i,当开始执行时候,i就不是最外层了,因为内层有一个作用域。就近。

(function(){
 for (var i = 0; i < 3; i++) {
 		setTimeout(
 			function(ii){
 				console.log(ii);
 			},1000*i,i);	
 }
})();

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值