《JavaScript入门-- 函数的执行时机》

JavaScript入门-- 函数的执行时机

js 的函数执行时机很重要,一不小心就容易踩坑,例如下面这两种情况:

情况一:

let i = 0
for(i = 0; i<6; i++){
	console.log(i)
}

情况二:

let i = 0
for(i = 0; i<6; i++){
	setTimeout(()=>{
    	console.log(i)
 	},0)
}

问两种情况打印出的 i 是多少?如果 js 基础不扎实就有可能踩坑。

答案是:

情况一:0、1、2、3、4、5 。

情况二:6、6、6、6、6、6。

情况二之所以与情况一不一样是因为 setTimeout 是延迟函数,js 在这种情况下需要先执行完 for 循环才能执行 setTimeout 函数的逻辑,而执行完 for 循环 i 的值就已经固定了,不会变,所以会打印出多个6。

解决办法:

想要解决问题,就要明白为什么会出现问题。

之所以产生上面的问题就是因为在 setTimeout 函数执行前 i 的值就已经固定了,如果想要情况二和情况一的行为相同那就想办法保留 i 在累加过程中的所有中间值,然后用这些中间值当作参数分别传入 setTimeout 函数中,所以常见办法有两种:

第一种:

for(let i = 0; i<6; i++){
	setTimeout(()=>{
    	console.log(i)
 	},0)
}

将 let 关键字放在 for 循环内部,这样每次循环的时候 js 会帮我们把 i 的所有中间值都保留在内存中,当 for 循环执行完后再一个一个传入 setTimeout 函数中执行代码逻辑。

第二种:

let i = 0
for(i = 0; i<6; i++){
	doLog(i)
}
function doLog(i){
	setTimeout(()=>{
    	console.log(i)
 	},0)
}

这样为什么也行? 当然也是保存了 i 的所有中间值了,因为 doLog 不是延迟函数所以会立即执行,而当 doLog 函数被调用的时候会将函数按照顺序放到调用栈中,而函数的参数会被拷贝一份副本跟 doLog 函数一起压栈,所以也会避免情况二发生。

当然肯定不止有这两种方式,任何能够将 i 的中间值都保留下来的方式,都有可能是解决办法之一。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值