关于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 ...
随机推荐
- 理解RxJava:(二)Operator,Operator
在第一部分,我讲解了RxJava的基本结构,也介绍了map()操作.然而,我能理解你仍旧不会选择使用Rxjava--你仍然还有很多东西没有学到.但是这个情况将很快得到改变.Rxjava一大部分的能力是 ...
- 线程安全集合 ConcurrentDictionary<TKey, TValue> 类
ConcurrentDictionary<TKey, TValue> 类 [表示可由多个线程同时访问的键/值对的线程安全集合.] 支持 .NET Framework 4.0 及以上. 示例 ...
- 事务复制中的snapshot
Snapshot agent读取article的信息,将article的内容和脚本放置到snapshot文件夹中: 接下来distribution agent会读取这些快照文件,传输到订阅,完 ...
- 精品素材:WALK & RIDE 单页网站模板下载
今天,很高兴能向大家分享一个响应式的,简约风格的 HTML5 单页网站模板.Walk & Ride 这款单页网站模板是现代风格的网页模板,简洁干净,像素完美,特别适合用于推广移动 APP 应用 ...
- iOS-动态计算Label的高度
一. 要求 1.根据网络请求的回来的字符串内容,动态计算Label的高度. 二. 注意点 1. 要注意设置label 的 numberOfLines 为0; 2. MAXFLOAT 的作用. 设置高度 ...
- iOS-验证码倒计时60秒
一. 要求 1.点击获取验证码按钮,60秒倒计时,按钮变成不可点击状态,按钮文字变成倒计时的秒数. 2.当倒计时为0的时候,释放掉定时器NSTimer,按钮变成可以点击状态,按钮文字变成"获 ...
- 另一个 OleDbParameterCollection 中已包含 OleDbParameter 错误分析及解决办法
程序非常简单,就是从一个表中取出一个符合要求的数据,如果取到,就把该数据对应的计数加1.也就是执行不同的两个SQL语句操作同一个表,并且这两个SQL的参数是一样的.在一个函数里完成这个调用.执行第二个 ...
- iOS实现图像素描效果
使用GPUImageSketchFilter对象实现图像素描效果 NSString *const kGPUImageSketchFragmentShaderString = SHADER_STRING ...
- [团队项目]expat不兼容BUG
本周五软工团队项目的第一次前后端全部对接时,出了一个蛋疼的错误. 最初起因是小丽叔出于安全的考虑,使用守护进程来跑Web服务器.守护进程(Daemon)是运行在后台的一种特殊进程,如果服务器用root ...
- C#方法的重载和方法的可变参数
方法的重载 1.方法重载的前提:方法名称必须一样 2.构成重载的条件:参数不一样(参数数量不一样,参数类型不一样) 方法的可变参数 1.可变参数的值的数量可以是0到多个. 2.可变参数调用的时候,没有 ...