详解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 相关文章推荐
jquery获取input表单值的代码
Apr 19 Javascript
js ondocumentready onmouseover onclick onmouseout 样式
Jul 22 Javascript
jquery关于图形报表的运用实现代码
Jan 06 Javascript
jQuery列表拖动排列具体实现
Nov 04 Javascript
jquery动态加载select下拉框示例代码
Dec 10 Javascript
jQuery formValidator表单验证
Jan 07 Javascript
简单理解js的prototype属性及使用
Dec 07 Javascript
Bootstrap基本组件学习笔记之分页(12)
Dec 08 Javascript
ES2015 Symbol 一种绝不重复的值
Dec 25 Javascript
30分钟快速实现小程序语音识别功能
Nov 27 Javascript
js实现的订阅发布者模式简单示例
Mar 14 Javascript
element-ui tree结构实现增删改自定义功能代码
Aug 31 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中实现记住密码自动登录的代码
2011/03/02 PHP
PHP实现的多彩标签效果代码分享
2014/08/21 PHP
php创建session的方法实例详解
2015/01/27 PHP
php猜单词游戏
2015/09/29 PHP
PHP转换文本框内容为HTML格式的方法
2016/07/20 PHP
javascript  Error 对象 错误处理
2008/05/18 Javascript
js修改input的type属性问题探讨
2013/10/12 Javascript
jQuery实现瀑布流布局详解(PC和移动端)
2020/09/01 Javascript
JavaScript生成带有缩进的表格代码
2016/06/15 Javascript
javascript 动态样式添加的简单实现
2016/10/11 Javascript
详解nodejs 文本操作模块-fs模块(三)
2016/12/22 NodeJs
JavaScript实现全选取消效果
2017/12/14 Javascript
JavaScript满天星导航栏实现方法
2018/03/08 Javascript
Mint UI组件库CheckList使用及踩坑总结
2018/12/20 Javascript
vue实现歌手列表字母排序下拉滚动条侧栏排序实时更新
2019/05/14 Javascript
vue+ElementUI 关闭对话框清空验证,清除form表单的操作
2020/08/06 Javascript
JS实现密码框效果
2020/09/10 Javascript
[53:15]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS OG
2018/03/30 DOTA
[36:22]VP vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python的加密模块md5、sha、crypt使用实例
2014/09/28 Python
Python中的闭包详细介绍和实例
2014/11/21 Python
详解如何用django实现redirect的几种方法总结
2018/11/22 Python
在pycharm中debug 实时查看数据操作(交互式)
2020/06/09 Python
Python实现寻找回文数字过程解析
2020/06/09 Python
Python爬虫获取op.gg英雄联盟英雄对位胜率的源码
2021/01/29 Python
python中@contextmanager实例用法
2021/02/07 Python
css图标制作教程制作云图标
2014/01/19 HTML / CSS
下面关于"联合"的题目的输出是什么
2013/08/06 面试题
四川成都导游欢迎词
2014/01/18 职场文书
保研推荐信
2014/05/09 职场文书
工程材料采购方案
2014/05/18 职场文书
省级青年文明号申报材料
2014/05/23 职场文书
求职信标题怎么写
2014/05/26 职场文书
2014年网管工作总结
2014/12/11 职场文书
楚门的世界观后感
2015/06/03 职场文书
无保留意见审计报告
2015/06/05 职场文书