详解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获取页面上某个元素的代码
Mar 13 Javascript
javascript的switch用法注意事项分析
Feb 02 Javascript
利用AngularJs实现京东首页轮播图效果
Sep 08 Javascript
JS+CSS3制作炫酷的弹窗效果
Nov 08 Javascript
Express框架之connect-flash详解
May 31 Javascript
在iframe中使bootstrap的模态框在父页面弹出问题
Aug 07 Javascript
JavaScript输入分钟、秒倒计时技巧总结(附代码)
Aug 17 Javascript
Angular搜索 过滤 批量删除 添加 表单验证功能集锦(实例代码)
Oct 25 Javascript
bootstrap Table的一些小操作
Nov 01 Javascript
基于substring()和substr()的使用以及区别(实例讲解)
Dec 28 Javascript
Vue实现简单分页器
Dec 29 Javascript
Vue使用NProgress进度条的方法
Sep 21 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获取搜索引擎关键字来源的函数(支持百度和谷歌等搜索引擎)
2012/10/03 PHP
php网站地图生成类示例
2014/01/13 PHP
PHP实现生成唯一编号(36进制的不重复编号)
2014/07/01 PHP
基于php实现随机合并数组并排序(原排序)
2015/11/26 PHP
PHP实现的简单分页类及用法示例
2016/05/06 PHP
深入理解PHP的远程多会话调试
2017/09/21 PHP
微信公众号实现扫码获取微信用户信息(网页授权)
2019/04/09 PHP
php设计模式之单例模式用法经典示例分析
2019/09/20 PHP
js中将HTMLCollection/NodeList/伪数组转换成数组的代码
2011/07/31 Javascript
js禁止页面复制功能禁用页面右键菜单示例代码
2013/08/29 Javascript
JavaScript设计模式之单件模式介绍
2014/12/28 Javascript
JavaScript中逗号运算符介绍及使用示例
2015/03/13 Javascript
JavaScript 浏览器对象模型BOM使用介绍
2015/04/13 Javascript
浅析location.href跨窗口调用函数
2016/11/22 Javascript
jQuery实现页面顶部下拉广告
2016/12/30 Javascript
JS跨域请求外部服务器的资源
2017/02/06 Javascript
js中setTimeout的妙用--防止循环超时
2017/03/06 Javascript
微信小程序实战篇之购物车的实现代码示例
2017/11/30 Javascript
微信小程序实现的picker多级联动功能示例
2019/05/23 Javascript
ES6 Class中实现私有属性的一些方法总结
2019/07/08 Javascript
2019最新21个MySQL高频面试题介绍
2020/02/06 Javascript
JavaScript禁止右击保存图片,禁止拖拽图片的实现代码
2020/04/28 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
go和python变量赋值遇到的一个问题
2017/08/31 Python
Python File readlines() 使用方法
2018/03/19 Python
python使用递归的方式建立二叉树
2019/07/03 Python
python装饰器代替set get方法实例
2019/12/19 Python
python爬虫把url链接编码成gbk2312格式过程解析
2020/06/08 Python
H5最强接口之canvas实现动态图形功能
2019/05/31 HTML / CSS
母亲节感恩寄语
2014/02/21 职场文书
库房管理员岗位职责
2014/03/09 职场文书
绿色出行口号
2014/06/18 职场文书
2014年应急工作总结
2014/12/11 职场文书
元旦晚会主持词开场白
2015/05/28 职场文书
未婚证明格式
2015/06/15 职场文书
《钓鱼的启示》教学反思
2016/02/18 职场文书