在聊setTimeout和setInterval這兩個事件的前,先聊另一個與之密切關聯的知識點,那就是
線程(thread)。而線程有經常跟另一個詞語--「進程」一塊兒出現。那麼何爲線程?何爲線程呢?關於線程,維基百科上是這麼解釋的:Thread (computing), a sequence of instructions that may execute in parallel with others(可能與其餘指令並行執行的指令序列)。而進程是這麼解釋的:Process (computing), a computer program, or running a program concurrently with other programs(一種計算機程序,或與其餘程序同時運行一個程序)。看起來有點繞,那麼舉一個形象點的例子,好比說打開電腦桌面的QQ,那麼這個就是一個進程,而你能夠在QQ上同時跟不一樣的人聊天、發離線文件、 發照片,那麼這一個個操做就是線程。「與其餘程序同時運行一個程序」,前面一個程序指的就是線程,然後面一個程序指的纔是進程。
在js解析器中,js的執行是單線程的,也就是說一個進程執行過程當中只能執行一個操做,不能同時執行幾個操做。這個與其餘後端的語言,如java,pyhton,甚至是js寫的node.js有較大區別,這跟主要處理的業務對象是有關係的。另一點,咱們還須要區分瀏覽器的線程問題,瀏覽器是多線程的,除了js引擎線程,它還同時執行其餘操做,例如:UI渲染線程,http請求線程,EventLoop輪詢的處理線程等等。
講了一大堆線程和進程,那麼js到底是如何處理setTimeout和setInterval的呢?
先舉兩個例子:
例子一:
setTimeout(
function colorTurn(){
box1.style.backgroundColor="yellow";
},3000);
box1.style.backgroundColor="blue";
在瀏覽器上:盒子先顯示藍色,3秒後顯示黃色
例子二:
setInterval(
function colorTurn(){
box2.style.backgroundColor="yellow";
},3000);
box2.style.backgroundColor="blue";
在瀏覽器上:盒子先顯示藍色,3秒後顯示黃色html
![](http://static.javashuo.com/static/loading.gif)
結果與例子一是同樣的,但實際上,setInterval與setTimeout是有很大區別的,setTimeout只執行一次,而setInterval以函數內的時間參數爲間隔不斷執行,直到用clearInterval清除。能夠用循環回調函數實現加法來驗證setInterval,我在這裏就不寫出來了。
例一抽象出來的函數定義:
function process1(){
//do something}
setTimeout(fucntion process2(){
//do something
},3000)
function process3(){
//do something}
例二抽象出來的函數定義:
function process1(){
//do something}
setInterval(fucntion process2(){
//do something
},3000)
function process3(){
//do something}
這兩個函數都涉及到了我上面談到的線程問題,setTimeout是使函數延遲必定時間後再執行,setInterval是使函數以必定時間間隔執行。
當js執行setTimeout函數時,會延遲必定的時間才執行。例一中,函數執行的順序爲process1-process3-process3。因爲js解析器是單線程的,因此必須是一條命令執行完後纔到下一條命令,因此process2必須等Process3甚至後面的process4執行完了,3秒鐘時間間隔到了它纔會去檢查線程,若是空閒,它會立刻執行,若是有程序在執行,那麼它會等當前程序執行完以後再執行。那麼,若是process3執行時間超過了3秒呢?這種狀況下,process2會一直等待,直到process3執行完畢它才執行。
同理,setInterval函數也是如此。不一樣的是,它會每隔必定時間,在這裏是3秒鐘檢查一下線程隊列,若是沒有程序(函數)在執行,那麼它執行,若是有程序在執行,那麼它會繼續等待,直到下一次的3秒以後。
再深刻一點:
若是是setTimeout(或setInterval)裏面嵌套setTimeout(或者setInterval)呢?那麼仍是那個原理,函數按序進入執行堆棧,必須是一段程序執行完後纔會執行下一段程序。嵌套在裏面的setTimeout會在上級setTimeout基礎上繼續等待一段時間,當等待時間到後,檢查線程隊列,若是空閒,就執行,若是有程序在執行,就繼續等待。執行的順序是外面的setTimeout會先於裏面的setTimeout。
另外有一點值得了解一下:
setTimeout和setInterval都是window的函數,因此setTimeout和setInerval也能夠寫成window.setTimeout和window.setInterval。平時爲了方便,每每省去了window而已。