详解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 AutoComplete自动完成 的使用方法实例
Mar 19 Javascript
JS的replace方法详细介绍
Nov 09 Javascript
angularJS结合canvas画图例子
Feb 09 Javascript
基于Vue.js的表格分页组件
May 22 Javascript
JavaScript蒙板(model)功能的简单实现代码
Aug 04 Javascript
React中ES5与ES6写法的区别总结
Apr 21 Javascript
浅谈node.js 命令行工具(cli)
May 10 Javascript
Javascript迭代、递推、穷举、递归常用算法实例讲解
Feb 01 Javascript
javascript实现简单打字游戏
Oct 29 Javascript
javascript实现简易的计算器
Jan 17 Javascript
前端性能优化建议
Sep 17 Javascript
js之ajax文件上传
May 13 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
一个查看session内容的函数
2006/10/09 PHP
解决phpcms更换javascript的幻灯片代码调用图片问题
2014/12/26 PHP
Linux系统递归生成目录中文件的md5的方法
2015/06/29 PHP
PHP框架实现WebSocket在线聊天通讯系统
2019/11/21 PHP
php反序列化长度变化尾部字符串逃逸(0CTF-2016-piapiapia)
2020/02/15 PHP
PNG背景在不同浏览器下的应用
2009/06/22 Javascript
javascript中对Attr(dom中属性)的操作示例讲解
2013/12/02 Javascript
jquery仿搜索自动联想功能代码
2014/05/23 Javascript
jQuery Easyui 下拉树组件combotree
2016/12/16 Javascript
Angularjs自定义指令Directive详解
2017/05/27 Javascript
利用jsonp与代理服务器方案解决跨域问题
2017/09/14 Javascript
深入浅析Vue中的Prop
2018/06/10 Javascript
详细分析Node.js 多进程
2020/06/22 Javascript
[03:02]生活中的Dendi之野外度假篇
2016/08/09 DOTA
用Python编写一个基于终端的实现翻译的脚本
2015/04/24 Python
Python使用正则表达式获取网页中所需要的信息
2018/01/29 Python
python实现名片管理系统
2018/11/29 Python
python opencv 批量改变图片的尺寸大小的方法
2019/06/28 Python
浅谈Python中的异常和JSON读写数据的实现
2020/02/27 Python
Python带参数的装饰器运行原理解析
2020/06/09 Python
基于matplotlib中ion()和ioff()的使用详解
2020/06/16 Python
如何用python批量调整视频声音
2020/12/22 Python
Python中生成ndarray实例讲解
2021/02/22 Python
一款利用html5和css3实现的3D滚动特效的教程
2015/01/04 HTML / CSS
浅析rem和em和px vh vw和% 移动端长度单位
2016/04/28 HTML / CSS
描述一下JVM加载class文件的原理机制
2013/12/08 面试题
Java中的异常处理机制的简单原理和应用
2013/04/27 面试题
致长跑运动员广播稿
2014/01/31 职场文书
产品质量承诺范本
2014/03/31 职场文书
就业协议书样本
2014/08/20 职场文书
观看《周恩来的四个昼夜》思想汇报
2014/09/12 职场文书
民警个人对照检查剖析材料
2014/09/17 职场文书
保外就医申请书范文
2015/08/06 职场文书
2016党员入党决心书
2015/09/22 职场文书
消防安全培训工作总结
2015/10/23 职场文书
2019暑假学生安全口号
2019/06/27 职场文书