詳解JS中定時器setInterval和setTImeout的this指向問題

在js中setTimeout和setInterval都是用來定時的一個功能,下面這篇文章主要給介紹了JS中setInterval和setTImeout的this指向問題,文中經過示例介紹的很詳細,有須要的朋友能夠參考借鑑,一塊兒來看看吧。

前言閉包

Js是一個單線程語言,能夠經過setTimeout()和setInterval()來設置代碼在指定時刻運行,前者是在指定時間後執行,後者是指每隔一段時間執行。二者的使用方法相似。app

最近在練習寫一個小例子的時候用到了定時器,發如今setInterval和setTimeout中傳入函數時,函數中的this會指向window對象,詳細的介紹經過一個示例展開,一塊兒來看看吧。函數

以下例:this

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.net

可是在setTimeout中傳入的不是函數時,this則指向當前對象,以下例:prototype

var num = 0;
function Obj (){
 this.num = 1,
 this.getNum = function(){
 console.log(this.num);
 },
 this.getNumLater = function(){
 setTimeout(console.log(this.num), 1000)
 }
}
var obj = new Obj; 
obj.getNum();//1  打印的爲obj.num,值爲1
obj.getNumLater()//1  打印的爲obj.num,值爲1

從以上兩個例子能夠看出,當在setTimeout中傳入的參數爲函數時,函數內部的this纔會指向window對象。線程

當在setTimeout中傳入了一個函數,若想要讓this指向正確的值,可使用如下兩種比較經常使用的方法來使this指向正確的值:指針

1.將當前對象的this存爲一個變量,定時器內的函數利用閉包來訪問這個變量code

以下:htm

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

以上兩種方法都是比較經常使用的,固然若是使用call或apply方法來代替bind方法,獲得的結果也是正確的,可是call方法會在調用以後當即執行,那樣也就沒有了延時的效果,定時器也就沒有用了,因此推薦使用上述兩種方法來將this傳進setTimeout和setInterval中。

 

本文轉載於腳本之家,做者:陌路黃昏後   的文章,原文連接:https://m.jb51.net/article/102232.htm

若有侵權,請告知刪除

相關文章
相關標籤/搜索