详解JS中定时器setInterval和setTImeout的this指向问题


Posted in Javascript onJanuary 06, 2017

前言

Js是一个单线程语言,可以通过setTimeout()和setInterval()来设置代码在指定时刻运行,前者是在指定时间后执行,后者是指每隔一段时间执行。两者的使用方法类似。

最近在练习写一个小例子的时候用到了定时器,发现在setInterval和setTimeout中传入函数时,函数中的this会指向window对象,详细的介绍通过一个示例展开,一起来看看吧。

如下例:

var num = 0;
function Obj (){
 this.num = 1,
 this.getNum = function(){
 console.log(this.num);
 },
 this.getNumLater = function(){
 setTimeout(function(){
  console.log(this.num);
 }, 1000)
 }
}
var obj = new Obj; 
obj.getNum();//1打印的为obj.num,值为1
obj.getNumLater()//0
打印的为window.num,值为0

从上述例子中可以看到setTimeout中函数内的this是指向了window对象,这是由于setTimeout()调用的代码运行在与所在函数完全分离的执行环境上. 这会导致这些代码中包含的 this 关键字会指向 window (或全局)对象。详细可参考MDN setTimeout

但是在setTimeout中传入的不是函数时,this则指向当前对象,如下例:

var num = 0;
function Obj (){
 this.num = 1,
 this.getNum = function(){
 console.log(this.num);
 },
 this.getNumLater = function(){
 setTimeout(console.log(this.num), 1000)
 }
}
var obj = new Obj; 
obj.getNum();//1打印的为obj.num,值为1
obj.getNumLater()//1
打印的为obj.num,值为1

从以上两个例子可以看出,当在setTimeout中传入的参数为函数时,函数内部的this才会指向window对象。

当在setTimeout中传入了一个函数,若想要让this指向正确的值,可以使用以下两种比较常用的方法来使this指向正确的值:

1.将当前对象的this存为一个变量,定时器内的函数利用闭包来访问这个变量

如下:

var num = 0;
function Obj (){
 var that = this; //将this存为一个变量,此时的this指向obj
 this.num = 1,
 this.getNum = function(){
 console.log(this.num);
 },
 this.getNumLater = function(){
 setTimeout(function(){
  console.log(that.num); //利用闭包访问that,that是一个指向obj的指针
 }, 1000)
 }
}
var obj = new Obj; 
obj.getNum();//1打印的为obj.num,值为1
obj.getNumLater()//1
打印的为obj.num,值为1

这种方法是将当前对象的引用放在一个变量里,定时器内部的函数来访问到这个变量,自然就可以得到当前的对象。

2.利用bind()方法

var num = 0;
function Obj (){
 this.num = 1,
 this.getNum = function(){
 console.log(this.num);
 },
 this.getNumLater = function(){
 setTimeout(function(){
  console.log(this.num);
 }.bind(this), 1000) //利用bind()将this绑定到这个函数上
 }
}
var obj = new Obj; 
obj.getNum();//1打印的为obj.num,值为1
obj.getNumLater()//1
打印的为obj.num,值为1

bind()方法是在Function.prototype上的一个方法,当被绑定函数执行时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this。在这个例子中,在调用setTimeout中的函数时,bind方法创建了一个新的函数,并将this传进新的函数,执行的结果也就是正确的了。关于bind方法可参考 MDN bind

以上两种方法都是比较常用的,当然如果使用call或apply方法来代替bind方法,得到的结果也是正确的,但是call方法会在调用之后立即执行,那样也就没有了延时的效果,定时器也就没有用了,所以推荐使用上述两种方法来将this传进setTimeout和setInterval中。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
菜鸟javascript基础整理1
Dec 06 Javascript
分页栏的web标准实现
Nov 01 Javascript
js控制鼠标事件移动及移出效果显示
Oct 19 Javascript
详细解读AngularJS中的表单验证编程
Jun 19 Javascript
浅谈JavaScript的Polymer框架中的事件绑定
Jul 29 Javascript
js学习总结之DOM2兼容处理顺序问题的解决方法
Jul 27 Javascript
vue中keep-alive的用法及问题描述
May 15 Javascript
vue定义全局变量和全局方法的方法示例
Aug 01 Javascript
JavaScript实现数字前补“0”的五种方法示例
Jan 03 Javascript
微信小程序实现富文本图片宽度自适应的方法
Jan 20 Javascript
vue addRoutes路由动态加载操作
Aug 04 Javascript
AngularJs的$http发送POST请求,php无法接收Post的数据问题及解决方案
Aug 13 Javascript
Jqprint实现页面打印
Jan 06 #Javascript
JS使用正则截取两个字符串之间的字符串实现方法详解
Jan 06 #Javascript
jQuery EasyUi 验证功能实例解析
Jan 06 #Javascript
jQuery编写网页版2048小游戏
Jan 06 #Javascript
利用JQuery实现datatables插件的增加和删除行功能
Jan 06 #Javascript
javascript正则表达式模糊匹配IP地址功能示例
Jan 06 #Javascript
bootstrap导航栏、下拉菜单、表单的简单应用实例解析
Jan 06 #Javascript
You might like
PHP判断文章里是否有图片的简单方法
2014/07/26 PHP
PHP+MySQL插入操作实例
2015/01/21 PHP
php使用文本统计访问量的方法
2016/05/12 PHP
PHP+Ajax实现上传文件进度条动态显示进度功能
2018/06/04 PHP
关于Curl在Swoole协程中的解决方案详析
2019/09/12 PHP
javascript 字符串连接的性能问题(多浏览器)
2008/11/18 Javascript
js压缩工具 yuicompressor 使用教程
2010/03/31 Javascript
js 获取屏幕各种宽高的方法(浏览器兼容)
2013/05/15 Javascript
浅析JavaScript原型继承的陷阱
2013/12/03 Javascript
中文输入法不触发onkeyup事件的解决办法
2014/07/09 Javascript
js+html5实现的自由落体运动效果代码
2016/01/28 Javascript
Vue2.0 http请求以及loading展示实例
2018/03/06 Javascript
浅谈VUE防抖与节流的最佳解决方案(函数式组件)
2019/05/22 Javascript
vue+openlayers绘制省市边界线
2020/12/24 Vue.js
[01:02:45]完美世界DOTA2联赛 LBZS vs Forest 第三场 11.07
2020/11/09 DOTA
Python Trie树实现字典排序
2014/03/28 Python
Python中使用asyncio 封装文件读写
2016/09/11 Python
Python使用内置json模块解析json格式数据的方法
2017/07/20 Python
python使用xpath中遇到:到底是什么?
2018/01/04 Python
Python Numpy库常见用法入门教程
2020/01/16 Python
django 装饰器 检测登录状态操作
2020/07/02 Python
加拿大消费电子和手机购物网站:The Source
2017/01/28 全球购物
意大利灯具购物网站:Lampade.it
2018/10/18 全球购物
澳大利亚Mocha官方网站:包、钱包、珠宝和配饰
2019/07/18 全球购物
德国咖啡批发商:Coffeefair
2019/08/26 全球购物
项目专员岗位职责
2013/12/04 职场文书
前台接待员岗位职责
2014/01/02 职场文书
公益广告语集锦
2014/03/13 职场文书
高一学生期末评语
2014/04/25 职场文书
运动会横幅标语
2014/06/17 职场文书
2015重阳节座谈会主持词
2015/07/30 职场文书
运动会跳远广播稿
2015/08/19 职场文书
2016年优秀少先队辅导员事迹材料
2016/02/26 职场文书
农村房屋租赁合同(范本)
2019/07/23 职场文书
Python3的进程和线程你了解吗
2022/03/16 Python
Mysql使用全文索引(FullText index)的实例代码
2022/04/03 MySQL