使用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才能夠。