详解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 nextSibling 与 getNextElement(node) 使用介绍
Oct 13 Javascript
用js来定义浏览器中一个左右浮动元素相对于页面主体宽度的位置的函数
Jan 21 Javascript
js循环改变div颜色具体方法
Jun 25 Javascript
JavaScript实现检查页面上的广告是否被AdBlock屏蔽了的方法
Nov 03 Javascript
jQuery和AngularJS的区别浅析
Jan 29 Javascript
js实现键盘上下左右键选择文字并显示在文本框的方法
May 07 Javascript
easyui combobox开启搜索自动完成功能的实例代码
Nov 08 Javascript
详解React中合并单元格的正确写法
Jan 08 Javascript
Jquery获取radio选中值实例总结
Jan 17 jQuery
JavaScript实现的滚动公告特效【基于jQuery】
Jul 10 jQuery
JS中的算法与数据结构之字典(Dictionary)实例详解
Aug 20 Javascript
解决Vue 刷新页面导航显示高亮位置不对问题
Dec 25 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
CI框架源码阅读,系统常量文件constants.php的配置
2013/02/28 PHP
PHP实现图片旋转效果实例代码
2014/10/01 PHP
PHP使用pdo连接access数据库并循环显示数据操作示例
2018/06/05 PHP
PHP利用百度ai实现文本和图片审核
2019/05/08 PHP
用js实现的仿sohu博客更换页面风格(简单版)
2007/03/22 Javascript
通过修改referer下载文件的方法
2008/05/11 Javascript
验证用户是否修改过页面的数据的实现方法
2008/09/26 Javascript
基于jquery的3d效果实现代码
2011/03/23 Javascript
SyntaxHighlighter语法高亮插件使用说明
2011/08/14 Javascript
javascript学习笔记(七) js函数介绍
2012/06/19 Javascript
Javascript中封装window.open解决不兼容问题
2014/09/28 Javascript
JS实现让网页背景图片斜向移动的方法
2015/02/25 Javascript
深入理解JavaScript系列(30):设计模式之外观模式详解
2015/03/03 Javascript
IE9+已经不对document.createElement向下兼容的解决方法
2015/09/14 Javascript
JavaScript多图片上传案例
2015/09/28 Javascript
Javascript技术难点之apply,call与this之间的衔接
2015/12/04 Javascript
谈谈我对JavaScript原型和闭包系列理解(随手笔记9)
2015/12/24 Javascript
JavaScript中Object.prototype.toString方法的原理
2016/02/24 Javascript
AngularJs 弹出模态框(model)
2016/04/07 Javascript
微信小程序实现留言功能
2018/10/31 Javascript
js继承的这6种方式!(上)
2019/04/23 Javascript
JavaScript中EventBus实现对象之间通信
2020/10/18 Javascript
[01:09:10]NB vs Liquid Supermajor小组赛 A组胜者组决赛 BO3 第一场 6.2
2018/06/04 DOTA
Python入门之modf()方法的使用
2015/05/15 Python
Python中使用装饰器来优化尾递归的示例
2016/06/18 Python
Python函数和模块的使用总结
2019/05/20 Python
我就是这样学习Python中的列表
2019/06/02 Python
通过案例解析python鸭子类型相关原理
2020/10/10 Python
表单button的outline在firefox浏览器下的问题
2012/12/24 HTML / CSS
标准化管理实施方案
2014/02/25 职场文书
党校培训自我鉴定范文
2014/04/10 职场文书
2014年十一国庆节活动方案
2014/09/16 职场文书
社团招新宣传语
2015/07/13 职场文书
2016春季幼儿园大班开学寄语
2015/12/03 职场文书
Spring Data JPA的Audit功能审计数据库的变更
2021/06/26 Java/Android
详解Go语言中配置文件使用与日志配置
2022/06/01 Golang