摘要:當間隔時間設置較小時,將會導致回調函數堆積。處理可能阻塞的代碼最簡單且最可控的方式就是在回調函數內部使用函數。但是很明顯,由于指定最大值的限制,還會有定時器沒有被清除掉。另外,盡量避免使用函數,從而避免可能導致的回調函數堆積現象。
由于 Javascript 是異步的,因此我們可以通過 setTimeout 和 setInterval 函數來指定特定時間執行代碼。
function foo() {} var id = setTimeout(foo, 1000); // returns a Number > 0
上例中,當 setTimeout 函數被調用時,它會返回一個標志延時的 ID 并計劃在大約 1000 毫秒后調用 foo 函數,函數 foo 將只會執行一次。
根據 Javascript 引擎的計時方法,以及 Javascript 單線程的本質,因此其他代碼執行時可能會阻塞此線程,我們無法保證 setTimeout 函數內調用的函數會在指定的時間被執行。
setTimeout 函數的第一個參數將會在全局作用域內執行,因此參數內的 this 將會指向全局對象。
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 本身。
setInterval 函數的堆調用從上文已知,setTimeout 中的回調函數只會執行一次,而 setInterval 函數,正如函數的名字一樣,它會每隔指定時間執行一次回調函數。
即使回調函數的執行被阻塞,setInterval 函數依然會繼續調用更多的回調函數。當間隔時間設置較小時,將會導致回調函數堆積。
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 函數現在可以自己控制是否繼續或終止。
手動清除定時器清除定時器可以通過傳遞指定的 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 并一起清除。
// clear "all" timeouts var biggestTimeoutId = window.setTimeout(function(){}, 1), i; for(i = 1; i <= biggestTimeoutId; i++) { clearTimeout(i); }eval 的隱式使用
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 都學習了一遍,基本上每一個章節都翻譯了一遍,同時加上了自己的一些想法和筆記,大概花了半個多月的時間,感覺這的的確確是個很適合自己的學習方法,有時候忘記某些概念,我立馬就能在自己的博客中找到相關的知識并及時回顧,由于出自自己的筆下,所以很快就能回憶起來。希望自己能堅持這個好的習慣,也希望自己的博文能給博友們帶來些許的幫助,大家相互學習,共同進步!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78124.html
摘要:然而,函數只有在當前作用域中直接被調用并且被調用的函數名為才會被執行。在全局作用域下,這個字符串會一直被執行,在這個情形下我們并沒有直接調用函數,也可以執行字符串。總結函數應該盡可能地避免使用。 Javascript 的 eval 函數可以在當前作用域執行一段包含 Javascript 代碼的字符串。 var foo = 1; function test() { var fo...
摘要:有兩個可以表示空的值,分別是和,比較有作用的是前者。訪問聲明但未初始化的變量。有返回值時函數的表達式沒有顯式的返回任何內容。然而,為了比較其他變量和值,我們需要提前取得的值。因此,從標準實行后,全局變量已經是不再可寫。 Javascript 有兩個可以表示空的值,分別是 undefined 和 null,比較有作用的是前者。 undefined undefined 是一種值為 un...
摘要:此時會自動插入分號,解析器將再次嘗試。工作原理下面的代碼沒有分號,因此解析器將會自己判斷在哪些地方插入分號。前置小括號在有前置小括號的情形時,解析器將不會自動插入分號。這不僅將保證代碼整體的一致性,也將有效地避免解析器對代碼行為的錯誤改變。 盡管 Javascript 有類似 C 的句法風格,但是它并不強制在代碼中使用分號,所以分號可能被省略。Javascript 并不是一個缺少分號的...
摘要:說明這次實現的雪花飄落的效果很簡單,主要是為了練習練習中的定時器,和。簡單說,意思就是用了這個定時器,能把兩次修改樣式的代碼分開執行,可以先把第一次修改的樣式渲染后,在進行第二次的修改,雪花就會動了。 說明 這次實現的雪花飄落的效果很簡單,主要是為了練習練習JavaScript中的定時器,setTimeout 和 setInterval。 效果圖 showImg(https://seg...
摘要:說明這次實現的雪花飄落的效果很簡單,主要是為了練習練習中的定時器,和。簡單說,意思就是用了這個定時器,能把兩次修改樣式的代碼分開執行,可以先把第一次修改的樣式渲染后,在進行第二次的修改,雪花就會動了。 說明 這次實現的雪花飄落的效果很簡單,主要是為了練習練習JavaScript中的定時器,setTimeout 和 setInterval。 效果圖 showImg(https://seg...
閱讀 668·2021-11-23 09:51
閱讀 3327·2021-10-11 10:58
閱讀 15496·2021-09-29 09:47
閱讀 3590·2021-09-01 11:42
閱讀 1297·2019-08-29 16:43
閱讀 1842·2019-08-29 15:37
閱讀 2124·2019-08-29 12:56
閱讀 1734·2019-08-28 18:21