问题描述

前些天在练习写一个小例子的时候用到了定时器,发现在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指向正确的值,可以使用以下三种比较常用的方法来使this指向正确的值:

1.将当前对象的this存为一个变量,定时器内的函数利用闭包来访问这个变量,如下:

var num = 0;
function Obj (){var that = this;    //将this存为一个变量,此时的this指向objthis.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

3. 箭头函数

var num = 0;
function Obj (){this.num = 1,this.getNum = function(){console.log(this.num);},this.getNumLater = function(){setTimeout(() => {console.log(this.num);}, 1000)    //箭头函数中的this总是指向外层调用者,也就是Obj}
}
var obj = new Obj;
obj.getNum();//1  打印的是obj.num,值为1
obj.getNumLater()//1  打印的是obj.num,值为1

ES6中的箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj,因此利用箭头函数就可以轻松解决这个问题。

以上三种方法都是比较常用的,当然如果使用call或apply方法来代替bind方法,得到的结果也是正确的,但是call方法会在调用之后立即执行,那样也就没有了延时的效果,定时器也就没有用了,所以推荐使用上述方法来将this传进setTimeout和setInterval中。

转载于:https://www.cnblogs.com/kid526940065/p/10912524.html

关于setInterval和setTImeout中的this指向问题相关推荐

  1. 关于setTimeout函数中的this指向问题

    为什么setTimeout函数的延迟执行函数中this指向window,但是延迟执行函数是箭头函数this指向obj? 根据下面的两点原因解释,foo和foo2中的this都指向obj,但是其中set ...

  2. 普通函数和箭头函数中的this指向

    普通函数的this指向Window function a(){console.log(this) } a() //Window Dom元素绑定事件时的this,句柄里的 this 值是该元素的引用 d ...

  3. html 取消settimeout,JavaScript中停止执行setInterval和setTimeout事件的方法

    js 代码中执行循环事件时,经常会用到 setInterval 和 setTimeout 这两个方法,关于这两个方法的细节这里不详细讨论了,简要分享下在需要停止循环事件的时候该如何操作. (1)set ...

  4. js中setInterval与setTimeout的区别

    一.setInterval与setTimeout的区别 1.setInterval setInterval() 方法可按照指定的周期来调用函数(以毫秒为单位) 语法: setInterval(函数表达 ...

  5. JS中setInterval、setTimeout不能传递带参数的函数的解决方法

    setInterval 和 setTimeout 这两个函数比较好用,但会遇到比如说我隔个几秒后要执行的函数是带参数的,这种情况怎么办?可以用匿名函数包装处理 //不带参数的函数function te ...

  6. 理解JavaScript中this的指向详解

    this的定义和理解: this是JavaScript语言的一个关键字,它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内使用. 1.this和执行环境对象有关,和函数的声明无关. var ...

  7. setInterval和setTimeout

    setInterval和setTimeout 1. 总结 1.1. setTimeout和setInterval()的时间间隔是不可动态修改的 1.1.1. 错误方式 1.1.2. 正确方式 1.2. ...

  8. 简述JS中THIS的指向?

    这里是修真院前端小课堂,每篇分享文从 八个方面深度解析前端知识/技能,本篇分享的是: [简述JS中THIS的指向?] 大家好,我是IT修真院武汉分院web第16期的学员孟晨,一枚正直纯洁善良的web程 ...

  9. JS中this的指向与改变this指向的三个方法

    目录 一.this指向的分类 1.全局函数的调用 2.对象中函数的调用 3.setTimeout与setInterval中的this 4.事件绑定中的this 5.箭头函数中的this 6.构造函数中 ...

最新文章

  1. PHP与Python哪个做网站产品好?
  2. QString和string互相转换乱码处理
  3. 【译】Using Machine Learning to Understand the Ethereum Blockchain
  4. Process和ProcessBuilder入门【原】
  5. 17、【 商品管理模块开发】——后台商品图片的springmvc和富文本上传以及ftp文件服务器的开发...
  6. 通过NSNotification来监听键盘弹出和弹回
  7. TVM:使用 Schedule 模板和 AutoTVM 来优化算子
  8. 注解 @CrossOrigin
  9. mysql 主主忽略错误_MySQL 主主报错: Fatal error: The slave I/O thread stops because master and slave have...
  10. [翻译]自定义Sharepoint的登陆页面
  11. [转载] python中list与string的转换
  12. 勒索病毒 -- “永恒之蓝”NSA 武器免疫工具
  13. 分享100个好看且实用的PPT模板
  14. 用java求可达矩阵_ISM算法(邻接矩阵求可达矩阵)Java实现
  15. 正则表达式的语法汇总
  16. python怎么加字幕_使用moviepy为电影添加字幕
  17. 百位LOL英雄联盟角色合集
  18. 虚拟化开源技术有哪些_您使用哪些开源虚拟化工具?
  19. 零跑股价再度上涨的原因到底是什么呢?
  20. 10个非常适合菜鸟练手的Python项目,墙裂建议收藏!

热门文章

  1. spring boot 教程(三)配置详解
  2. 如何设置电脑自动锁屏_办公族如何设置自动关闭显示器,让显示屏锁屏,防止偷看你电脑。...
  3. android volley 请求参数,android – Volley – 如何发送DELETE请求参数?
  4. Leetcode-213:打家劫舍 II
  5. 系统学习NLP(十二)--文本表示综述
  6. python 矩量法_矩量法:β二项分布
  7. azure kinect三维点云_三维重建技术,你捋清楚了吗?本文适合小白
  8. hive窗口函数入门
  9. Windows核心编程_窗口蒙版效果
  10. centos7---mysql5.7主从复制读写分离