详解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 相关文章推荐
在网页中控制wmplayer播放器
Jul 01 Javascript
如何简单地用YUI做JavaScript动画
Mar 10 Javascript
地震发生中逃生十大法则
May 12 Javascript
Javascript浅谈之引用类型
Dec 18 Javascript
js实现无限级树形导航列表效果代码
Sep 23 Javascript
javascript实现的网站访问量统计代码
Dec 20 Javascript
js实现的二分查找算法实例
Jan 21 Javascript
Bootstrap零基础学习第一课之模板
Jul 18 Javascript
Javascript动画效果(2)
Oct 11 Javascript
JavaScript trim 实现去除字符串首尾指定字符的简单方法
Dec 27 Javascript
VueJs组件prop验证简单介绍
Sep 12 Javascript
vue 内联样式style中的background用法说明
Aug 05 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函数之日期时间函数date()使用详解
2013/09/09 PHP
php数组添加与删除单元的常用函数实例分析
2015/02/16 PHP
初识laravel5
2015/03/02 PHP
JQuery,Extjs,YUI,Prototype,Dojo 等JS框架的区别和应用场景简述
2010/04/15 Javascript
js 小数取整的函数
2010/05/10 Javascript
JavaScript访问样式表代码
2010/10/15 Javascript
Js控制弹窗实现在任意分辨率下居中显示
2013/08/01 Javascript
JS控制阿拉伯数字转为中文大写示例代码
2013/09/04 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
从零学JS之你需要了解的几本书
2014/05/19 Javascript
使用pjax实现无刷新更改页面url
2015/02/05 Javascript
JSONP原理及简单实现
2016/06/08 Javascript
一种基于浏览器的自动小票机打印实现方案(js版)
2016/07/26 Javascript
JavaScript面试开发常用的知识点总结
2016/08/08 Javascript
JavaScript实现省市联动过程中bug的解决方法
2017/12/04 Javascript
vue 本地服务不能被外部IP访问的完美解决方法
2018/10/29 Javascript
微信小程序实现笑脸评分功能
2018/11/03 Javascript
基于JavaScript实现猜数字游戏代码实例
2020/07/30 Javascript
[01:11:11]Alliance vs RNG 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
Python中暂存上传图片的方法
2015/02/18 Python
pymssql数据库操作MSSQL2005实例分析
2015/05/25 Python
Python中的异常处理相关语句基础学习笔记
2016/07/11 Python
Python Socket传输文件示例
2017/01/16 Python
Python实现自定义顺序、排列写入数据到Excel的方法
2018/04/23 Python
flask框架视图函数用法示例
2018/07/19 Python
Django中的ajax请求
2018/10/19 Python
python 实现对文件夹中的图像连续重命名方法
2018/10/25 Python
浅谈keras使用中val_acc和acc值不同步的思考
2020/06/18 Python
Python基于pillow库实现生成图片水印
2020/09/14 Python
python上下文管理的使用场景实例讲解
2021/03/03 Python
Sixt美国租车:高端豪华车型自驾体验
2017/09/02 全球购物
十岁生日父母答谢词
2014/01/18 职场文书
平面设计专业求职信
2014/08/09 职场文书
2015年文明创建工作总结
2015/04/30 职场文书
2015年节能减排工作总结
2015/05/14 职场文书
Java练习之潜艇小游戏的实现
2022/03/16 Java/Android