详解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评估用户输入密码的强度(Knockout版)
Nov 30 Javascript
javascript从右边截取指定字符串的三种实现方法
Nov 29 Javascript
JavaScript关闭当前页面(窗口)不带任何提示
Mar 26 Javascript
用jQuery获取table中行id和td值的实现代码
May 19 Javascript
javascript中获取元素标签中间的内容的实现方法
Oct 08 Javascript
基于ES6 Array.of的用法(实例讲解)
Sep 05 Javascript
JavaScript实现的原生态Tab标签页功能【兼容IE6】
Sep 18 Javascript
Node.js引入UIBootstrap的方法示例
May 11 Javascript
vue组件从开发到发布的实现步骤
Nov 11 Javascript
微信小程序bindtap事件与冒泡阻止详解
Aug 08 Javascript
Node.JS获取GET,POST数据之queryString模块使用方法详解
Feb 06 Javascript
JavaScript canvas实现雪花随机动态飘落
Feb 08 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开发的一些注意点总结
2010/10/12 PHP
PHP与C#分别格式化文件大小的代码
2011/05/14 PHP
php数组查找函数in_array()、array_search()、array_key_exists()使用实例
2014/04/29 PHP
PHP实现的随机红包算法示例
2017/08/14 PHP
PHP实现浏览器格式化显示XML的方法示例
2019/01/22 PHP
PHP读取Excel内的图片(phpspreadsheet和PHPExcel扩展库)
2019/11/19 PHP
细品javascript 寻址,闭包,对象模型和相关问题
2009/04/27 Javascript
jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、Chrome、Opera
2009/08/28 Javascript
JQuery页面图片切换和新闻列表滚动效果的具体实现
2013/09/26 Javascript
遍历DOM对象内的元素属性示例代码
2014/02/08 Javascript
30个经典的jQuery代码开发技巧
2014/12/15 Javascript
AngularJS控制器详解及示例代码
2016/08/16 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
2017/06/11 jQuery
IntersectionObserver实现图片懒加载的示例
2017/09/29 Javascript
LayUI switch 开关监听 获取属性值、更改状态的方法
2019/09/21 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
2020/10/02 Javascript
[05:59]带你看看DPC的台前幕后
2021/03/11 DOTA
python使用sqlite3时游标使用方法
2018/03/13 Python
python实现监控某个服务 服务崩溃即发送邮件报告
2018/06/21 Python
对pandas中时间窗函数rolling的使用详解
2018/11/28 Python
详解10个可以快速用Python进行数据分析的小技巧
2019/06/24 Python
django框架创建应用操作示例
2019/09/26 Python
如何基于python操作json文件获取内容
2019/12/24 Python
python自动化unittest yaml使用过程解析
2020/02/03 Python
PyQt5如何将.ui文件转换为.py文件的实例代码
2020/05/26 Python
python 装饰器重要在哪
2021/02/14 Python
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
个人主要事迹材料
2014/08/26 职场文书
2014年班主任德育工作总结
2014/12/05 职场文书
单位接收函格式
2015/01/30 职场文书
2015年药品销售工作总结范文
2015/05/25 职场文书
《走遍天下书为侣》教学反思
2016/02/22 职场文书
Python基础之hashlib模块详解
2021/05/06 Python
MySQL数据库⾼可⽤HA实现小结
2022/01/22 MySQL
IIS服务器中设置HTTP重定向访问HTTPS
2022/04/29 Servers
react中useState使用:如何实现在当前表格直接更改数据
2022/08/05 Javascript