使用js中的定时器(setInterval,setTimeout),很容易会遇到this指向的问题。es6
直接上例子:babel
1 var name = 'my name is window'; 2 var obj = { 3 name: 'my name is obj', 4 fn: function () { 5 var timer = null; 6 clearInterval(timer); 7 timer = setInterval(function () { 8 console.log(this.name); //my name is window 9 }, 1000) 10 } 11 }
在这里,从this.name能够看出this的指向是window。app
若是没有特殊指向,setInterval和setTimeout的回调函数中this的指向都是window。这是由于JS的定时器方法是定义在window下的。可是平时不少场景下,都须要修改this的指向。这里总结了几种:函数
一、最经常使用的方法:在外部函数中将this存为一个变量,回调函数中使用该变量,而不是直接使用this。this
1 var name = 'my name is window'; 2 var obj = { 3 name: 'my name is obj', 4 fn: function () { 5 var that = this; 6 var timer = null; 7 clearInterval(timer); 8 timer = setInterval(function () { 9 console.log(that.name); //my name is obj 10 }, 1000) 11 } 12 }
在fn中加了var that = this; 回调函数中使用that代替this便可。这种方法最多见,使用也最普遍。es5
二、使用bind()方法(bind()为ES5的标准,低版本IE下有兼容问题,能够引入es5-shim.js解决)spa
bind()的做用相似call和apply,都是修改this指向。可是call和apply是修改this指向后函数会当即执行,而bind则是返回一个新的函数,它会建立一个与原来函数主体相同的新函数,新函数中的this指向传入的对象。code
1 var name = 'my name is window'; 2 var obj = { 3 name: 'my name is obj', 4 fn: function () { 5 var timer = null; 6 clearInterval(timer); 7 timer = setInterval(function () { 8 console.log(this.name); //my name is obj 9 }.bind(this), 1000) 10 } 11 }
在这里为何不能用call和apply,是由于call和apply不是返回函数,而是当即执行函数,那么,就失去了定时器的做用。对象
三、使用es6的箭头函数:箭头函数的最大做用就是this指向。blog
1 var name = 'my name is window'; 2 var obj = { 3 name: 'my name is obj', 4 fn: function () { 5 var timer = null; 6 clearInterval(timer); 7 timer = setInterval(() => { 8 console.log(this.name); //my name is obj 9 }, 1000) 10 } 11 }
箭头函数没有本身的this,它的this继承自外部函数的做用域。因此,在该例中,定时器回调函数中的this,是继承了fn的this。固然箭头函数也有兼容问题,要是兼容低版本ie,须要使用babel编译,而且引入es5-shim.js才能够。