首頁 > web前端 > js教程 > 主體

js中的setTimeout()函數

一个新手
發布: 2017-09-21 09:45:41
原創
2492 人瀏覽過

       在js中,setTimeout()函數是全域變量,無論在哪裡它都是全域變數而不是局部變數。所以下面這個例子的結果可能會讓你大吃一驚:

function A() {
    this.b = function() {
        console.log(1)
    }
}
var c = new A()
setTimeout(c.b, 10)
登入後複製

        可能有些人認為上面這個例子輸出的結果是1,但是結果是undefined。這是因為setTImeout()函數是全域變量,它把裡面的c.b發到全域變數中,而全域變數中沒有b這個屬性,所以回傳的undefined。

       在js中,setTimeout()函數的運作機制是這樣的,setInterval()函數也是一樣。將指定的程式碼移出本次執行,等到下一輪Event Loop時,再檢查是否到了指定時間。如果到了,就執行對應的程式碼;如果不到,就等到再下一輪Event Loop時重新判斷。這意味著,setTimeout指定的程式碼,必須等到本次執行的所有程式碼都執行完,才會執行。 ·

        每回合Event Loop時,都會將「任務佇列」中需要執行的任務,一次執行完畢。 setTimeout和setInterval都是把任務加入到「任務佇列」的尾端。因此,它們實際上要等到目前腳本的所有同步任務執行完,然後再等到本次Event Loop的「任務佇列」的所有任務執行完,才會開始執行。由於前面的任務到底需要多少時間執行完,是不確定的,所以沒有辦法保證,setTimeout和setInterval指定的任務,一定會按照預定時間執行。

        所以如果前面有一個函數被阻塞了,就一直等待函數執行完才能運作。因為js是單線程的,所以比較容易會發生阻塞的。

        在setTimeout()函數中,最快的運作時間是4毫秒,即使將延遲參數寫為0或負數,它都不會立刻的運作。在延遲參數為0或負數時,需要等待當前腳步的同步任務和event loop(即任務隊列)執行完畢才開始執行,由於參數為0或負數,只是比其他setTimeout()函數盡可能早的運行函數,而參數為0或負數本身優先權相同。如:

setTimeout('console.log(1)',0)
console.log(2)
登入後複製

        回傳的結果是2 1

setTimeout('console.log(1)',0)
setTimeout('console.log(2)',-1)
setTimeout('console.log(3)',-1)
setTimeout('console.log(4)',0)
登入後複製

        回傳的結果是1 2 3 4

        在setTimeout()中,還有一點值得注意的。那就是它的第一個參數必須是需要編譯的程式碼或是函數方法。所以像上面的例子中,console.log()被單引號括起來變成一個字串,在setTimeout中有一個eval()函數可以將字串進行編譯。如果我們將console.log()方法沒有用單引號括起來,那麼整個setTimeout()函數就會立即執行,而不會考慮有沒有延遲參數。如我在美的的美雲智數面試遇見過的這一題一樣:

console.log(1)

setTimeout(console.log(2),0)
  
console.log(3)
  
setTimeout(console.log(4),-1)
登入後複製

        返回的結果是1 2 3 4,如果將單引號括起來,返回的結果是1 3 2 4

        在js中想要清除setTimeout計時器,需要clearTimeout()這個函數。具體用法如下所示:

var a = setTimeout('console.log(1)', 1)
clearTimeout(a)
登入後複製

        最後貼出一道題看看畢業了沒有,對比下面三段代碼,看分別輸出上面:

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 0);
    console.log(i);
}
登入後複製
for (var i = 0; i < 3; i++) {
    setTimeout((function() {
        console.log(i);
    })(i), 0);
    console.log(i);
}
登入後複製
for (var i = 0; i < 3; i++) {
    setTimeout((function(i) {
        return function() {
            console.log(i);
        };
    })(i), 0);
    console.log(i);  
}
登入後複製

        這道題設計了一些js的作用域的問題,我會特別寫一篇文章介紹es5中作用域和es6中的作用域發生了哪些變化。     

以上是js中的setTimeout()函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板