詳解JS中定時(shí)器setInterval和setTImeout的this指向問(wèn)題
前言
Js是一個(gè)單線程語(yǔ)言,可以通過(guò)setTimeout()和setInterval()來(lái)設(shè)置代碼在指定時(shí)刻運(yùn)行,前者是在指定時(shí)間后執(zhí)行,后者是指每隔一段時(shí)間執(zhí)行。兩者的使用方法類似。
最近在練習(xí)寫(xiě)一個(gè)小例子的時(shí)候用到了定時(shí)器,發(fā)現(xiàn)在setInterval和setTimeout中傳入函數(shù)時(shí),函數(shù)中的this會(huì)指向window對(duì)象,詳細(xì)的介紹通過(guò)一個(gè)示例展開(kāi),一起來(lái)看看吧。
如下例:
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中函數(shù)內(nèi)的this是指向了window對(duì)象,這是由于setTimeout()
調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上. 這會(huì)導(dǎo)致這些代碼中包含的 this 關(guān)鍵字會(huì)指向 window (或全局)對(duì)象。詳細(xì)可參考MDN setTimeout
但是在setTimeout中傳入的不是函數(shù)時(shí),this則指向當(dāng)前對(duì)象,如下例:
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
從以上兩個(gè)例子可以看出,當(dāng)在setTimeout中傳入的參數(shù)為函數(shù)時(shí),函數(shù)內(nèi)部的this才會(huì)指向window對(duì)象。
當(dāng)在setTimeout中傳入了一個(gè)函數(shù),若想要讓this指向正確的值,可以使用以下兩種比較常用的方法來(lái)使this指向正確的值:
1.將當(dāng)前對(duì)象的this存為一個(gè)變量,定時(shí)器內(nèi)的函數(shù)利用閉包來(lái)訪問(wèn)這個(gè)變量
如下:
var num = 0; function Obj (){ var that = this; //將this存為一個(gè)變量,此時(shí)的this指向obj this.num = 1, this.getNum = function(){ console.log(this.num); }, this.getNumLater = function(){ setTimeout(function(){ console.log(that.num); //利用閉包訪問(wèn)that,that是一個(gè)指向obj的指針 }, 1000) } } var obj = new Obj; obj.getNum();//1 打印的為obj.num,值為1 obj.getNumLater()//1 打印的為obj.num,值為1
這種方法是將當(dāng)前對(duì)象的引用放在一個(gè)變量里,定時(shí)器內(nèi)部的函數(shù)來(lái)訪問(wèn)到這個(gè)變量,自然就可以得到當(dāng)前的對(duì)象。
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綁定到這個(gè)函數(shù)上 } } var obj = new Obj; obj.getNum();//1 打印的為obj.num,值為1 obj.getNumLater()//1 打印的為obj.num,值為1
bind()
方法是在Function.prototype
上的一個(gè)方法,當(dāng)被綁定函數(shù)執(zhí)行時(shí),bind方法會(huì)創(chuàng)建一個(gè)新函數(shù),并將第一個(gè)參數(shù)作為新函數(shù)運(yùn)行時(shí)的this。在這個(gè)例子中,在調(diào)用setTimeout中的函數(shù)時(shí),bind方法創(chuàng)建了一個(gè)新的函數(shù),并將this傳進(jìn)新的函數(shù),執(zhí)行的結(jié)果也就是正確的了。關(guān)于bind方法可參考 MDN bind
以上兩種方法都是比較常用的,當(dāng)然如果使用call或apply方法來(lái)代替bind方法,得到的結(jié)果也是正確的,但是call方法會(huì)在調(diào)用之后立即執(zhí)行,那樣也就沒(méi)有了延時(shí)的效果,定時(shí)器也就沒(méi)有用了,所以推薦使用上述兩種方法來(lái)將this傳進(jìn)setTimeout和setInterval中。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- javascript中SetInterval與setTimeout的定時(shí)器用法
- JavaScript定時(shí)器setTimeout()和setInterval()詳解
- 定時(shí)器(setTimeout/setInterval)調(diào)用帶參函數(shù)失效解決方法
- 理解javascript定時(shí)器中的setTimeout與setInterval
- Javascript中setTimeOut和setInterval的定時(shí)器用法
- JavaScript中定時(shí)器setTimeout()和setInterval()的用法
- JavaScript定時(shí)器setTimeout、setInterval使用詳解
相關(guān)文章
JavaScript遍歷查找數(shù)組中最大值與最小值的方法示例
這篇文章主要介紹了JavaScript遍歷查找數(shù)組中最大值與最小值的方法,結(jié)合實(shí)例形式分析了javascript基于數(shù)組遍歷、判斷實(shí)現(xiàn)最大值與最小值計(jì)算的相關(guān)操作技巧,需要的朋友可以參考下2019-05-05值得分享的輕量級(jí)Bootstrap Table表格插件
這篇文章為大家分享了輕量級(jí)Bootstrap Table表格插件,以表格的形式顯示的數(shù)據(jù),支持單選,復(fù)選框,排序,分頁(yè),顯示/隱藏列等操作,感興趣的小伙伴們可以參考一下2016-05-05JS實(shí)現(xiàn)數(shù)組按升序及降序排列的方法
這篇文章主要介紹了JS實(shí)現(xiàn)數(shù)組按升序及降序排列的方法,涉及javascript針對(duì)數(shù)組的簡(jiǎn)單排序操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-04-04可能被忽略的一些JavaScript數(shù)組方法細(xì)節(jié)
這篇文章主要給大家介紹了一些可能被忽略的JavaScript數(shù)組方法細(xì)節(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02js解決url傳遞中文參數(shù)亂碼問(wèn)題的方法詳解
前后臺(tái)用js傳參過(guò)程中,如果是中文就容易出現(xiàn)亂碼,下面這篇文章主要給大家介紹了關(guān)于js解決url傳遞中文參數(shù)亂碼問(wèn)題的的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05純 JS 實(shí)現(xiàn)放大縮小拖拽功能(完整代碼)
這篇文章主要介紹了純js實(shí)現(xiàn)放大縮小拖拽功能,文中給大家提到了在開(kāi)發(fā)過(guò)程中遇到的一些問(wèn)題及解決方法,需要的朋友可以參考下2019-11-11