关于setInterval和setTImeout中的this指向问题
问题描述
前些天在练习写一个小例子的时候用到了定时器,发现在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指向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
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中。
关于setInterval和setTImeout中的this指向问题的更多相关文章
- setInterval和setTImeout中的this指向问题
问题:在setInterval和setTimeout中传入函数时,函数中的this会指向window对象 解决方法: 1. 将当前对象的this存为一个变量,定时器内的函数利用闭包来访问这个变量.va ...
- JavaScript中this的指向(转载)
转载自:http://www.cnblogs.com/dongcanliang/p/7054176.html 前言 this 指向问题是入坑前端必须了解知识点,现在迎来了ES6时代,因为箭头函数的出现 ...
- JS里设定延时:js中SetInterval与setTimeout用法
js中SetInterval与setTimeout用法 JS里设定延时: 使用SetInterval和设定延时函数setTimeout 很类似.setTimeout 运用在延迟一段时间,再进行某项操 ...
- javascript中window与document对象、setInterval与setTimeout定时器的用法与区别
一.写在前面 本人前端菜鸟一枚,学习前端不久,学习过程中有很多概念.定义在使用时容易混淆,在此给向我一样刚踏入前端之门的童鞋们归纳一下.今天给大家分享一下js中window与document对象.se ...
- JS中setInterval、setTimeout不能传递带参数的函数的解决方法
setInterval 和 setTimeout 这两个函数比较好用,但会遇到比如说我隔个几秒后要执行的函数是带参数的,这种情况怎么办?可以用匿名函数包装处理 //不带参数的函数 function t ...
- Javascript定时器中的this指向
使用js中的定时器(setInterval,setTimeout),很容易会遇到this指向的问题. 直接上例子: var name = 'my name is window'; var obj = ...
- Javascript回调函数中的this指向问题
使用js中的定时器(setInterval,setTimeout),很容易会遇到this指向的问题. 直接上例子: 1 var name = 'my name is window'; 2 var ob ...
- Vue中关于this指向的问题
由Vue管理的函数 例如: computed 计算属性 watch 监视属性 filters (Vue3中已弃用且不再支持) 过滤器 .... 上述属性里配置的函数不要采用箭头函数写法,因为箭头函数没 ...
- JavaScript DOM 编程艺术·setInterval与setTimeout的动画实现解析
先贴上moveElement()函数的大纲,为了方便观看,删了部分代码,完整版粘到文章后面. function moveElement(elementID,final_x,final_y,interv ...
随机推荐
- Eplan 2D安装版布局,部件、端子竖放
部件竖放,不是通过变量的选择实现,而是通过设置实现的,具体设置在: 选项-设置-用户-2D安装板布局: 部件方向-更改为 垂直 部件放置-旋转角度-更改为90° 这样在连续放置部件的时候就变为竖放了, ...
- GPT分区基础知识
大硬盘和WIN8系统,让我们从传统的BIOS+MBR模式升级到UEFI+GPT模式,现在购买的电脑,都是预装WIN8系统,为了更好的支持2TB硬盘,更快速的启动win8,预装系统都采取了GPT分区的格 ...
- 转载好文:如何进行基于情境数据的个性化EDM数据营销
根据Adobe和DMA(Direct Marketing Association)的<实时营销洞察报告> (Real-Time Marketing Insights Study),77%的 ...
- 安卓开发笔记——自定义广告轮播Banner(实现无限循环)
关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...
- npm命令总结
统一切换到项目目录 安装redux :npm install -save redux 安装react-redux : npm install -save react-redux
- seajs中spm压缩工具使用
seajs是个好东西,用起来很方便,但是她的压缩工具spm确不被网友看好,因为使用起来很麻烦,捯饬了一天多,终于勉强能压缩了,这里就简单记录一下. 按照地址:http://www.zhangxinxu ...
- HandlerMethodArgumentResolver数据绑定无效
因项目中action参数过多,并且是一些通用的查询参数,所以准备进行对参数统一封装为Map对象,然后由action中传入service中进行处理,查询spring的资料发现可以通过实现HandlerM ...
- 编写高质量JS代码的68个有效方法(十)
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- C#对象与XMl文件之间的相互转换
C#提供三种序列化方式,分别为: 1.是使用BinaryFormatter进行串行化: 2.使用SoapFormatter进行串行化: 3.使用XmlSerializer进行串行化.其中对于Binar ...
- CSS魔法堂:Position定位详解
一.Position各属性值详解 1. static :默认值,元素将按照正常文档流规则排列. 2. relative :相对定位,元素仍然处于正常文档流当中,但可以通过left.top. ...