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 相关文章推荐
javascript实现的像java、c#之类的sleep暂停的函数代码
Mar 04 Javascript
JavaScript打字小游戏代码
Dec 26 Javascript
一个JavaScript的求爱小特效
May 09 Javascript
javascript中数组的多种定义方法和常用函数简介
May 09 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
Mar 10 Javascript
vue实现可增删查改的成绩单
Oct 27 Javascript
JS中静态页面实现微信分享功能
Feb 06 Javascript
JavaScript省市级联下拉菜单实例
Feb 14 Javascript
JS操作时间 - UNIX时间戳的简单介绍(必看篇)
Aug 16 Javascript
详解微信小程序中组件通讯
Oct 30 Javascript
jquery+php后台实现省市区联动功能示例
May 23 jQuery
浅谈Vue3.0之前你必须知道的TypeScript实战技巧
Sep 11 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
关于BIG5-HKSCS的解决方法
2007/03/20 PHP
Thinkphp实现自动验证和自动完成
2015/12/19 PHP
Zend Framework教程之Zend_Controller_Plugin插件用法详解
2016/03/07 PHP
php 提交表单 关闭layer弹窗iframe的实例讲解
2018/08/20 PHP
javascript 获取表单file全路径
2009/12/31 Javascript
js对象数组按属性快速排序
2011/01/31 Javascript
点击进行复制的JS代码实例
2013/08/23 Javascript
js获取当前地址 JS获取当前URL的示例代码
2014/02/26 Javascript
js通过八个点 拖动改变div大小的实现方法
2014/03/05 Javascript
js实现右下角提示框的方法
2015/02/03 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
2015/08/26 Javascript
详解JavaScript语言的基本语法要求
2015/11/20 Javascript
jQuery实现点击弹出背景变暗遮罩效果实例代码
2016/06/24 Javascript
AngularJS  双向数据绑定详解简单实例
2016/10/20 Javascript
javascript 封装Date日期类实例详解
2017/05/28 Javascript
解决vue项目打包后提示图片文件路径错误的问题
2018/07/04 Javascript
使用vue2.0创建的项目的步骤方法
2018/09/25 Javascript
[01:03:59]2018DOTA2亚洲邀请赛3月30日 小组赛B组VGJ.T VS Secret
2018/03/31 DOTA
Python中tell()方法的使用详解
2015/05/24 Python
CentOS安装pillow报错的解决方法
2016/01/27 Python
用Python编写简单的微博爬虫
2016/03/04 Python
Python减少循环层次和缩进的技巧分析
2016/03/15 Python
Python基于聚类算法实现密度聚类(DBSCAN)计算【测试可用】
2018/12/26 Python
pycharm创建一个python包方法图解
2019/04/10 Python
Python argparse模块应用实例解析
2019/11/15 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
无需压缩软件,用python帮你操作压缩包
2020/08/17 Python
前后端结合实现amazeUI分页效果
2020/08/21 HTML / CSS
材料采购员岗位职责
2013/12/17 职场文书
教育学习自我评价
2014/02/03 职场文书
4S店售后客服自我评价
2014/04/09 职场文书
社区戒毒工作方案
2014/06/04 职场文书
2014学生会工作总结报告
2014/12/02 职场文书
后勤工作个人总结
2015/02/28 职场文书
资产移交协议书
2016/03/24 职场文书
vue-cli4.5.x快速搭建项目
2021/05/30 Vue.js