详解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 相关文章推荐
ExtJs的Date格式字符代码
Dec 30 Javascript
自己动手开发jQuery插件教程
Aug 25 Javascript
jquery中dom操作和事件的实例学习 仿yahoo邮箱登录框的提示效果
Nov 30 Javascript
jquery实现当滑动到一定位置时固定效果
Jun 17 Javascript
require.js深入了解 require.js特性介绍
Sep 04 Javascript
js为什么不能正确处理小数运算?
Dec 29 Javascript
canvas实现绘制吃豆鱼效果
Jan 12 Javascript
node.js中grunt和gulp的区别详解
Jul 17 Javascript
三种Webpack打包方式(小结)
Sep 19 Javascript
在axios中使用params传参的时候传入数组的方法
Sep 25 Javascript
详解在vue-cli3.0中自定css、js和图片的打包路径
Aug 26 Javascript
解决vue-router 嵌套路由没反应的问题
Sep 22 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 什么是PEAR?
2009/03/19 PHP
php download.php实现代码 跳转到下载文件(response.redirect)
2009/08/26 PHP
php定时计划任务的实现方法详解
2013/06/06 PHP
PHP模糊查询技术实例分析【附源码下载】
2019/03/07 PHP
动态刷新 dorado树的js代码
2009/06/12 Javascript
JavaScript Event学习第六章 事件的访问
2010/02/07 Javascript
关于js注册事件的常用方法
2013/04/03 Javascript
JS调用页面表格导出excel示例代码
2014/03/18 Javascript
JQuery $.each遍历JavaScript数组对象实例
2014/09/01 Javascript
jQuery图片渐变特效的简单实现
2016/06/25 Javascript
HTML5 JS压缩图片并获取图片BASE64编码上传
2020/11/16 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
2016/11/16 Javascript
DropDownList控件绑定数据源的三种方法
2016/12/24 Javascript
JS中使用textPath实现线条上的文字
2017/12/25 Javascript
jQuery中内容过滤器简单用法示例
2018/03/31 jQuery
jQuery实现的页面弹幕效果【测试可用】
2018/08/17 jQuery
对angularJs中$sce服务安全显示html文本的实例
2018/09/30 Javascript
简单的Python的curses库使用教程
2015/04/11 Python
Python中处理字符串的相关的len()方法的使用简介
2015/05/19 Python
python实现俄罗斯方块
2018/06/26 Python
解决vscode python print 输出窗口中文乱码的问题
2018/12/03 Python
python实现连续图文识别
2018/12/18 Python
Python设计模式之抽象工厂模式原理与用法详解
2019/01/15 Python
python三方库之requests的快速上手
2019/03/04 Python
python支付宝支付示例详解
2019/08/22 Python
python实现超市商品销售管理系统
2019/11/22 Python
Python2.x与3​​.x版本有哪些区别
2020/07/09 Python
澳大利亚首屈一指的在线购物目的地:Kogan.com
2017/02/02 全球购物
法学专业自我鉴定
2014/02/05 职场文书
有多年工作经验的自我评价
2014/03/02 职场文书
校园文明标语
2014/06/13 职场文书
单位在职证明书
2014/09/11 职场文书
教师三严三实学习心得体会
2014/10/11 职场文书
2016学校先进党组织事迹材料
2016/02/29 职场文书
CSS 圆形进度栏
2021/04/06 HTML / CSS
php访问对象中的成员的实例方法
2021/11/17 PHP