因爲 Javascript
是異步的,所以咱們能夠經過 setTimeout
和 setInterval
函數來指定特定時間執行代碼。git
function foo() {} var id = setTimeout(foo, 1000); // returns a Number > 0
上例中,當 setTimeout
函數被調用時,它會返回一個標誌延時的 ID
並計劃在大約 1000
毫秒後調用 foo
函數,函數 foo
將只會執行一次。
根據 Javascript
引擎的計時方法,以及 Javascript
單線程的本質,所以其餘代碼執行時可能會阻塞此線程,咱們沒法保證 setTimeout
函數內調用的函數會在指定的時間被執行。setTimeout
函數的第一個參數將會在全局做用域內執行,所以參數內的 this
將會指向全局對象。github
function Foo() { this.value = 42; this.method = function() { // this refers to the global object console.log(this.value); // will log undefined }; setTimeout(this.method, 500); } new Foo();
這裏要注意一個常犯的錯誤,setTimeout
函數的第一個參數指的是函數對象自己,不能寫成相似 setTimeout(foo(), 1000)
,由於 foo()
是函數返回值,而不是 foo
自己。異步
從上文已知,setTimeout
中的回調函數只會執行一次,而 setInterval
函數,正如函數的名字同樣,它會每隔指定時間執行一次回調函數。
即便回調函數的執行被阻塞,setInterval
函數依然會繼續調用更多的回調函數。當間隔時間設置較小時,將會致使回調函數堆積。ide
function foo(){ // something that blocks for 1 second } setInterval(foo, 1000);
上述代碼中,函數 foo
被調用後將被阻塞一秒鐘。函數
最簡單且最可控的方式就是在回調函數內部使用 setTimeout
函數。學習
function foo(){ // something that blocks for 1 second setTimeout(foo, 1000); } foo();
這樣不只封裝了 setTimeout
的調用,同時也阻止了可能存在的回調函數堆積。foo
函數如今能夠本身控制是否繼續或終止。this
清除定時器能夠經過傳遞指定的 ID
給 clearTimeout
或 clearInterval
函數。線程
var id = setTimeout(foo, 1000); clearTimeout(id);
Javascript
中並無內置的函數方法來清除全部的定時器(timeout
或 interval
),不過咱們能夠使用一種暴力的方法來清除全部的定時器。翻譯
// clear "all" timeouts for(var i = 1; i < 1000; i++) { clearTimeout(i); }
可是很明顯,因爲指定最大值的限制,還會有定時器沒有被清除掉。因爲 ID
會隨着定時器被調用的增長而增長,所以更好的方法是記錄下最大的 ID
並一塊兒清除。code
// clear "all" timeouts var biggestTimeoutId = window.setTimeout(function(){}, 1), i; for(i = 1; i <= biggestTimeoutId; i++) { clearTimeout(i); }
setTimeout
和 setInterval
函數的第一個參數也能夠接收字符串,可是儘可能不要使用這個功能,由於這會在內部調用 eval
函數來執行這段字符串。
function foo() { // will get called } function bar() { function foo() { // never gets called } setTimeout('foo()', 1000); } bar();
因爲 eval
函數並無在上例中被直接調用,所以傳遞到 setTimeout
函數的字符串將會在全局做用域下被執行,因此不會調用函數 bar
內部的 foo
函數。
建議儘可能不要在使用定時器函數時經過字符串形式來傳遞參數。
function foo(a, b, c) {} // NEVER use this setTimeout('foo(1, 2, 3)', 1000) // Instead use an anonymous function setTimeout(function() { foo(a, b, c); }, 1000)
不要使用字符串做爲 setTimeout
或 setInterval
函數的參數,當須要向回調函數中傳遞參數時,咱們能夠用匿名函數的,在匿名函數內部執行回調函數。
另外,儘可能避免使用 setInterval
函數,從而避免可能致使的回調函數堆積現象。
http://bonsaiden.github.io/JavaScript-Garden/#other.timeouts
終於將整個 Javascript
Garden
都學習了一遍,基本上每個章節都翻譯了一遍,同時加上了本身的一些想法和筆記,大概花了半個多月的時間,感受這的的確確是個很適合本身的學習方法,有時候忘記某些概念,我立馬就能在本身的博客中找到相關的知識並及時回顧,因爲出自本身的筆下,因此很快就能回憶起來。但願本身能堅持這個好的習慣,也但願本身的博文能給博友們帶來些許的幫助,你們相互學習,共同進步!