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 相关文章推荐
jquery重复提交请求的原因浅析
May 23 Javascript
js 动态修改css文件的方法
Aug 05 Javascript
jquery+css3实现会动的小圆圈效果
Jan 27 Javascript
基于javascript实现精确到毫秒的倒计时限时抢购
Apr 17 Javascript
JS简单实现DIV相对于浏览器固定位置不变的方法
Jun 17 Javascript
Node.js读写文件之批量替换图片的实现方法
Sep 07 Javascript
js仿拉勾网首页穿墙广告效果
Mar 08 Javascript
js获取css的各种样式并且设置他们的方法
Aug 22 Javascript
微信小程序实现日历功能
Nov 27 Javascript
vuex页面刷新后数据丢失的方法
Jan 17 Javascript
Python版实现微信公众号扫码登陆
May 28 Javascript
Vue生命周期activated之返回上一页不重新请求数据操作
Jul 26 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
DOTA2 玩家自创拉野攻略 特色英雄快速成长篇
2020/04/20 DOTA
php中显示数组与对象的实现代码
2011/04/18 PHP
php制作unicode解码工具(unicode编码转换器)代码分享
2013/12/24 PHP
php实现的太平洋时间和北京时间互转的自定义函数分享
2014/08/19 PHP
php验证码实现代码(3种)
2015/09/07 PHP
分享一个漂亮的php验证码类
2016/09/29 PHP
PHP实现重载的常用方法实例详解
2017/10/18 PHP
使用jQuery validate 验证注册表单实例演示
2013/03/25 Javascript
基于jquery的文章中所有图片width大小批量设置方法
2013/08/01 Javascript
浅析jquery某一元素重复绑定的问题
2014/01/03 Javascript
jQuery产品间断向下滚动效果核心代码
2014/05/08 Javascript
深入探密Javascript数组方法
2015/01/08 Javascript
js 自带的 map() 方法全面了解
2016/08/16 Javascript
JS正则替换去空格的方法
2017/03/24 Javascript
vue中如何引入jQuery和Bootstrap
2017/04/10 jQuery
深入理解JavaScript创建对象的多种方式以及优缺点
2017/06/01 Javascript
JavaScript设计模式之代理模式详解
2017/06/09 Javascript
详解利用 Vue.js 实现前后端分离的RBAC角色权限管理
2017/09/15 Javascript
web前端页面生成exe可执行文件的方法
2018/02/08 Javascript
vue学习之Vue-Router用法实例分析
2020/01/06 Javascript
Vue实现Layui的集成方法步骤
2020/04/10 Javascript
[02:10]探秘浦东源深体育馆 DOTA2 Supermajor不见不散
2018/05/17 DOTA
python通过smpt发送邮件的方法
2015/04/30 Python
python处理大数字的方法
2015/05/27 Python
python中zip()方法应用实例分析
2016/04/16 Python
python3.6数独问题的解决
2019/01/21 Python
Django使用redis缓存服务器的实现代码示例
2019/04/28 Python
浅谈pycharm导入pandas包遇到的问题及解决
2020/06/01 Python
湖南卫视在线视频媒体平台:芒果TV
2019/10/30 全球购物
Miller Harris官网:英国小众香水品牌
2020/09/24 全球购物
如何撰写岗位职责
2014/02/01 职场文书
投资建议书模板
2014/05/12 职场文书
关于教师节的广播稿
2014/09/10 职场文书
八项规定个人对照检查材料思想汇报
2014/09/25 职场文书
中秋节慰问信
2015/02/15 职场文书
该怎么书写道歉信?
2019/07/03 职场文书