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 相关文章推荐
JQERY limittext 插件0.2版(长内容限制显示)
Aug 27 Javascript
jquery $.ajax各个事件执行顺序
Oct 15 Javascript
js实现动态改变字体大小代码
Jan 02 Javascript
js获取IP地址的方法小结
Jul 01 Javascript
js获取checkbox复选框选中的选项实例
Aug 24 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
jQuery 1.9.1源码分析系列(十五)之动画处理
Dec 03 Javascript
AngularJS入门教程之XHR和依赖注入详解
Aug 18 Javascript
JavaScript 闭包机制详解及实例代码
Oct 10 Javascript
使用jquery判断一个元素是否含有一个指定的类(class)实例
Feb 12 Javascript
JavaScript实现省市区三级联动
Feb 13 Javascript
基于Cesium绘制抛物弧线
Nov 18 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 url 加密解密函数代码
2011/08/26 PHP
PHP身份证校验码计算方法
2016/08/10 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
jquery.fileEveryWhere.js 一个跨浏览器的file显示插件
2011/10/24 Javascript
nodejs获取本机内网和外网ip地址的实现代码
2014/06/01 NodeJs
JavaScript设计模式之外观模式介绍
2014/12/28 Javascript
JavaScript设计模式之原型模式(Object.create与prototype)介绍
2014/12/28 Javascript
Javascript中的匿名函数与封装介绍
2015/03/15 Javascript
JavaScript中匿名函数用法实例
2015/03/23 Javascript
javascript数组克隆简单实现方法
2015/12/16 Javascript
JS获取当前脚本文件的绝对路径
2016/03/02 Javascript
js 自带的 map() 方法全面了解
2016/08/16 Javascript
jQGrid Table操作列中点击【操作】按钮弹出按钮层的实现代码
2016/12/05 Javascript
JS脚本加载后执行相应回调函数的操作方法
2018/02/28 Javascript
微信小程序学习笔记之获取位置信息操作图文详解
2019/03/29 Javascript
JS面试题中深拷贝的实现讲解
2020/05/07 Javascript
mapboxgl区划标签避让不遮盖实现的代码详解
2020/07/01 Javascript
Jquery如何使用animation动画效果改变背景色的代码
2020/07/20 jQuery
Java中重定向输出流实现用文件记录程序日志
2015/06/12 Python
TF-IDF与余弦相似性的应用(一) 自动提取关键词
2017/12/21 Python
Python3中的json模块使用详解
2018/05/05 Python
python实现定时压缩指定文件夹发送邮件
2020/12/22 Python
Windows10下 python3.7 安装 facenet的教程
2019/09/10 Python
python中pdb模块实例用法
2021/01/15 Python
新西兰优惠网站:Treat Me
2019/07/04 全球购物
党员培训思想汇报
2014/01/07 职场文书
工业自动化专业自荐信范文
2014/04/10 职场文书
学生安全承诺书
2014/05/22 职场文书
入党积极分子学习优秀共产党员先进事迹思想汇报
2014/09/13 职场文书
2014个人年终工作总结范文
2014/12/15 职场文书
2015年毕业生个人自荐书
2015/03/24 职场文书
2015年综治宣传月活动总结
2015/03/25 职场文书
项目验收申请报告
2015/05/15 职场文书
篮球拉拉队口号
2015/12/25 职场文书
《少年闰土》教学反思
2016/02/18 职场文书
​(迎国庆)作文之我爱我的祖国
2019/09/19 职场文书