for循环 + setTimeout 结合一些示例(前端面试题)


Posted in Javascript onAugust 30, 2017

一、背景

最近在翻看以前的老书《node.js开发指南》,恰好碰到 for 循环 + setTimeout 的经典例子,于是重新梳理了思路并记录下。

二、写在前面,setTimeout 和 setInterval 的执行机制

在日常编码中,你会发现,给 setTimeout 和 setInterval 设定延迟时间往往并不准,或者干脆 setTimeout(function(){xxx},0) 也不是立马执行(特别是有耗时代码在前),这是因为 js 是单线程的,有一个事件队列机制,setTimeout 和 setInterval 的回调会到了延迟时间塞入事件队列中,排队执行。

setTimeout :延时 delay 毫秒之后,啥也不管,直接将回调函数加入事件队列。

setInterval :延时 delay 毫秒之后,先看看事件队列中是否存在还没有执行的回调函数( setInterval 的回调函数),如果存在,就不要再往事件队列里加入回调函数了。

看下面示例:

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

结果:1 秒之后,同时输出 5 个 5。

因为 for 循环会先执行完(同步优先于异步优先于回调),这时五个 setTimeout 的回调全部塞入了事件队列中,然后 1 秒后一起执行了。

三、正文

接下来就是那道经典的代码:

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

结果:5 5 5 5 5

为什么不是 1 2 3 4 5,问题出在作用域上。

因为 setTimeout 的 console.log(i); 的i是 var 定义的,所以是函数级的作用域,不属于 for 循环体,属于 global。等到 for 循环结束,i 已经等于 5 了,这个时候再执行 setTimeout 的五个回调函数(参考上面对事件机制的阐述),里面的 console.log(i); 的 i 去向上找作用域,只能找到 global下 的 i,即 5。所以输出都是 5。

解决办法:人为给 console.log(i); 创造作用域,保存i的值。

解决办法一

for (var i = 0; i < 5; i++) { 
  (function(i){   //立刻执行函数
    setTimeout(function (){
      console.log(i); 
     },1000); 
  })(i); 
}

这里用到立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了。

解决办法二

for (let i = 0; i < 5; i++) {   //let 代替 var
  setTimeout(function (){
    console.log(i); 
   },1000); 
}

let 为代码块的作用域,所以每一次 for 循环,console.log(i); 都引用到 for 代码块作用域下的i,因为这样被引用,所以 for 循环结束后,这些作用域在 setTimeout 未执行前都不会被释放。

四、补充

在写示例代码的过程中,发现一个语法点:

function a(i){ 
  console.log(i);  
 }
for (var i = 0; i < 5; i++) { 
  setTimeout(a(i),1000); 
}

报错:

TypeError: "callback" argument must be a function
at setTimeout (timers.js:421:11)
……

百度了下,原来 setTimeout 不支持传带参数的函数,可以再用一个匿名函数包装下它吧,见下面代码:

function a(i){ 
  console.log(i);  
}
for (var i = 0; i < 5; i++) { 
  setTimeout(function(){ //用匿名函数包装
    a(i);
  },1000); 
}

总结

以上所述是小编给大家介绍的for循环 + setTimeout 结合一些示例(前端面试题),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
一个简单的js鼠标划过切换效果
Jun 30 Javascript
动态的创建一个元素createElement及删除一个元素
Jan 24 Javascript
JS判断、校验MAC地址的2个实例
May 05 Javascript
关于JavaScript中name的意义冲突示例介绍
May 29 Javascript
javascript获取当前的时间戳的方法汇总
Jul 26 Javascript
AngularJS打开页面隐藏显示表达式用法示例
Dec 25 Javascript
在DWR中实现直接获取一个JAVA类的返回值的两种方法
Dec 25 Javascript
tracking.js页面人脸识别插件使用方法
Apr 16 Javascript
深入浅析Vue中mixin和extend的区别和使用场景
Aug 01 Javascript
CountUp.js数字滚动插件使用方法详解
Oct 17 Javascript
vue移动端使用canvas签名的实现
Jan 15 Javascript
JS实现电脑虚拟键盘打字测试
Jun 24 Javascript
详解使用nvm管理多版本node的方法
Aug 30 #Javascript
jquery插件开发之选项卡制作详解
Aug 30 #jQuery
浅谈angular.js跨域post解决方案
Aug 30 #Javascript
详解a++和++a的区别
Aug 30 #Javascript
详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)
Aug 30 #Javascript
angular4 如何在全局设置路由跳转动画的方法
Aug 30 #Javascript
浅谈Vue.js应用的四种AJAX请求数据模式
Aug 30 #Javascript
You might like
PHP出错界面
2006/10/09 PHP
用PHP连接MySQL代码的参数说明
2008/06/07 PHP
PHP 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
2014/06/12 PHP
PHP使用xmllint命令处理xml与html的方法
2014/12/15 PHP
PHP答题类应用接口实例
2015/02/09 PHP
php转换颜色为其反色的方法
2015/04/27 PHP
php有效防止同一用户多次登录
2015/11/19 PHP
PHP开发之归档格式phar文件概念与用法详解【创建,使用,解包还原提取】
2017/11/17 PHP
javascript操作cookie的文章(设置,删除cookies)
2010/04/01 Javascript
Firefox中使用outerHTML的2种解决方法
2014/06/07 Javascript
js限制文本框只能输入数字方法小结
2014/06/16 Javascript
JS实现闪动的title消息提醒效果
2014/06/20 Javascript
JavaScript的jQuery库中ready方法的学习教程
2015/08/14 Javascript
javaScript知识点总结(必看篇)
2016/06/10 Javascript
RGB和YUV 多媒体编程基础详细介绍
2016/11/04 Javascript
微信小程序使用radio显示单选项功能【附源码下载】
2017/12/11 Javascript
详解VUE 数组更新
2017/12/16 Javascript
基于bootstrap页面渲染的问题解决方法
2018/08/09 Javascript
vue-router权限控制(简单方式)
2018/10/29 Javascript
微信小程序实现一个简单swiper代码实例
2019/12/30 Javascript
Vue Object 的变化侦测实现代码
2020/04/15 Javascript
操作Windows注册表的简单的Python程序制作教程
2015/04/07 Python
Anaconda多环境多版本python配置操作方法
2017/09/12 Python
Python中实现最小二乘法思路及实现代码
2018/01/04 Python
基于Python实现迪杰斯特拉和弗洛伊德算法
2020/05/27 Python
python基于gevent实现并发下载器代码实例
2019/11/01 Python
使用python创建生成动态链接库dll的方法
2020/05/09 Python
HTML5 通信API 跨域门槛将不再高、数据推送也不再是梦
2013/04/25 HTML / CSS
美国知名的百货清仓店:Neiman Marcus Last Call
2016/08/03 全球购物
办护照工作证明范本
2014/01/14 职场文书
家长会学生演讲稿
2014/04/26 职场文书
应届生面试求职信
2014/07/02 职场文书
银行求职信范文怎么写
2015/03/20 职场文书
保密法制宣传月活动总结
2015/05/07 职场文书
python实现简单倒计时功能
2021/04/21 Python
CSS SandBox应用场景及常见问题
2022/06/25 HTML / CSS