JavaScript 的 setTimeout
函數詳解:實現延遲執行
setTimeout
是 JavaScript 中的原生函數,用於在指定延遲(毫秒)後調用函數或執行代碼片段。這在許多場景下非常有用,例如:在用戶瀏覽頁面一段時間後顯示彈出窗口,或在移除元素懸停效果前添加短暫延遲(防止誤操作)。
關鍵要點:
setTimeout
函數允許在指定毫秒數的延遲後執行函數或代碼片段,這對於諸如在一定瀏覽時間後顯示彈出窗口之類的任務非常有用。 setTimeout
接受函數引用作為第一個參數,該引用可以是函數名稱、引用函數的變量或匿名函數。它也可以執行代碼字符串,但不建議這樣做,因為這樣會降低可讀性、安全性並降低速度。 setTimeout
執行的回調函數。但是,在延遲之後列出參數的替代方法與 IE9 及以下版本不兼容。 setTimeout
執行的代碼中,this
的值在與調用它的函數不同的執行上下文中運行,這在 this
關鍵字的上下文很重要時可能會導致問題。這可以使用 bind
、庫函數或箭頭函數來解決。 setTimeout
的返回值是一個數字 ID,可用於結合 clearTimeout
函數取消計時器。 setTimeout
使用示例
以下代碼塊顯示了一個簡單的示例,該示例將在 2 秒(2000 毫秒)的超時後將消息打印到控制台:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
為了更詳細地演示這個概念,下面的演示在點擊按鈕兩秒鐘後顯示一個彈出窗口:(請訪問 CodePen 查看演示)
語法
根據 MDN 文檔,setTimeout
的語法如下:
const timeoutID = setTimeout(code); const timeoutID = setTimeout(code, delay); const timeoutID = setTimeout(functionRef); const timeoutID = setTimeout(functionRef, delay); const timeoutID = setTimeout(functionRef, delay[, arg1, arg2, /* … ,*/ argN])
其中:
timeoutID
是一個數字 ID,可與 clearTimeout
結合使用以取消計時器。 scope
指的是 Window
接口或 WorkerGlobalScope
接口。 functionRef
是計時器到期後要執行的函數。 code
是一種替代語法,允許您包含字符串而不是函數,該字符串在計時器到期時進行編譯和執行。 delay
是函數調用應延遲的毫秒數。如果省略,則默認為 0。 arg1
, ..., argN
是傳遞給 functionRef
指定的函數的其他參數。 注意:方括號 []
表示可選參數。
setTimeout
與 window.setTimeout
您會注意到,有時語法中包含 window.setTimeout
。這是為什麼呢?
在瀏覽器中運行代碼時,scope
將指代全局 window
對象。 setTimeout
和 window.setTimeout
指的是同一個函數,唯一的區別是,在第二個語句中,我們將 setTimeout
方法作為 window
對象的屬性來引用。
在我看來,這增加了複雜性,而好處卻微乎其微。如果您定義了另一種 setTimeout
方法,該方法將在作用域鏈中優先找到並返回,那麼您可能還有更大的問題需要擔心。
在本教程中,我將省略 window
,但最終,您選擇哪種語法取決於您自己。
setTimeout
方法的使用示例
setTimeout
方法接受函數引用作為第一個參數。
這可以是函數的名稱:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
引用函數的變量(函數表達式):
const timeoutID = setTimeout(code); const timeoutID = setTimeout(code, delay); const timeoutID = setTimeout(functionRef); const timeoutID = setTimeout(functionRef, delay); const timeoutID = setTimeout(functionRef, delay[, arg1, arg2, /* … ,*/ argN])
或者匿名函數:
function greet() { alert('Howdy!'); } setTimeout(greet, 2000);
如上所述,也可以將代碼字符串傳遞給 setTimeout
以供其執行:
const greet = function() { alert('Howdy!'); }; setTimeout(greet, 2000);
但是,由於以下原因,不建議這樣做:
eval
,這是一種潛在的安全風險。 傳遞參數給 setTimeout
在基本場景中,首選的跨瀏覽器方法是使用匿名函數作為第一個參數將參數傳遞給 setTimeout
執行的回調函數。
在下面的示例中,我們從 animals
數組中選擇一個隨機動物,並將此隨機動物作為參數傳遞給 makeTalk
函數。然後,setTimeout
以一秒的延遲執行 makeTalk
函數:
setTimeout(() => { alert('Howdy!'); }, 2000);
注意:我使用了一個常規函數(getRandom
)從數組中返回一個隨機元素。也可以使用箭頭函數將其編寫為函數表達式:
setTimeout('alert("Howdy!");', 2000);
我們將在下一節介紹箭頭函數。這裡有一個包含上述代碼的 CodePen(您需要打開控制台才能查看輸出)。
替代方法
從文章頂部的語法可以看出,傳遞參數給 setTimeout
執行的回調函數還有第二種方法。這涉及在延遲之後列出任何參數。
參考我們之前的示例,這將給我們:
function makeTalk(animal) { const noises = { cat: 'purr', dog: 'woof', cow: 'moo', pig: 'oink', } console.log(`A ${animal} goes ${noises[animal]}.`); } function getRandom(arr) { return arr[Math.floor(Math.random() * arr.length)]; } const animals = ['cat', 'dog', 'cow', 'pig']; const randomAnimal = getRandom(animals); setTimeout(() => { makeTalk(randomAnimal); }, 1000);
不幸的是,這在 IE9 或以下版本中不起作用,其中參數作為 undefined
傳遞。如果您不幸需要支持 IE9,則 MDN 上提供了一個 polyfill。
this
關鍵字的問題
setTimeout
執行的代碼在其與調用它的函數不同的執行上下文中運行。當 this
關鍵字的上下文很重要時,這會成為問題:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
此輸出的原因是,在第一個示例中,this
指向dog
對象,而在第二個示例中,this
指向全局window
對象(它沒有sound
屬性) 。
為了解決這個問題,有各種方法……
顯式設置 this
的值
您可以使用bind
來實現,bind
方法創建一個新函數,當調用該函數時,其this
關鍵字將設置為提供的值(在本例中為dog
對象) 。這將給我們:
const timeoutID = setTimeout(code); const timeoutID = setTimeout(code, delay); const timeoutID = setTimeout(functionRef); const timeoutID = setTimeout(functionRef, delay); const timeoutID = setTimeout(functionRef, delay[, arg1, arg2, /* … ,*/ argN])
使用庫
許多庫都帶有內置函數來解決此問題。例如,jQuery 的 jQuery.proxy()
方法。它接受一個函數並返回一個新函數,該函數將始終具有特定上下文。在本例中,那將是:
function greet() { alert('Howdy!'); } setTimeout(greet, 2000);
在 setTimeout
中使用箭頭函數
箭頭函數是在 ES6 中引入的。它們比常規函數的語法短得多:
const greet = function() { alert('Howdy!'); }; setTimeout(greet, 2000);
當然,您可以將它們與 setTimeout
一起使用,但是需要注意一點——箭頭函數沒有自己的 this
值。相反,它們使用封閉詞法上下文的 this
值。
使用常規函數:
setTimeout(() => { alert('Howdy!'); }, 2000);
使用箭頭函數:
setTimeout('alert("Howdy!");', 2000);
在第二個示例中,this
指向全局 window
對象(同樣,它沒有 sound
屬性)。
這在將箭頭函數與 setTimeout
一起使用時可能會讓我們陷入困境。之前我們看到瞭如何為 setTimeout
中調用的函數提供正確的 this
值:
function makeTalk(animal) { const noises = { cat: 'purr', dog: 'woof', cow: 'moo', pig: 'oink', } console.log(`A ${animal} goes ${noises[animal]}.`); } function getRandom(arr) { return arr[Math.floor(Math.random() * arr.length)]; } const animals = ['cat', 'dog', 'cow', 'pig']; const randomAnimal = getRandom(animals); setTimeout(() => { makeTalk(randomAnimal); }, 1000);
當在引入的方法中使用箭頭函數時,這將不起作用,因為箭頭函數沒有它自己的 this
值。該方法仍將記錄 undefined
。
使用箭頭函數和 setTimeout
編寫更簡潔的代碼
但是,因為箭頭函數沒有自己的 this
值,所以它也可以為我們帶來優勢。
考慮這樣的代碼:
const getRandom = arr => arr[Math.floor(Math.random() * arr.length)];
可以使用箭頭函數更簡潔地重寫它:
setTimeout(makeTalk, 1000, randomAnimal);
如果您想了解箭頭函數的入門知識,請閱讀“ES6 箭頭函數:JavaScript 中簡潔的語法”。
取消計時器
正如我們在文章開頭了解到的那樣,setTimeout
的返回值是一個數字 ID,可與 clearTimeout
函數結合使用以取消計時器:
function greet() { console.log('Howdy!'); } setTimeout(greet, 2000);
讓我們看看它的實際效果。在下面的 Pen 中,如果您點擊“開始倒計時”按鈕,倒計時將開始。如果倒計時完成,小貓就贏了。但是,如果您按下“停止倒計時”按鈕,計時器將被停止並重置。 (如果您在倒計時達到零時沒有看到很酷的效果,請使用嵌入底部右側的按鈕重新運行 Pen。)
總結
在本文中,我演示瞭如何使用 setTimeout
來延遲函數的執行。我還展示瞭如何將參數傳遞給 setTimeout
,如何在其回調函數內部維護 this
值,以及如何取消計時器。
setTimeout
JavaScript 函數的常見問題解答
setTimeout
在 JavaScript 中是什麼?
setTimeout
是 JavaScript 中的內置函數,允許您在指定的延遲(以毫秒為單位)後安排函數或代碼段的執行。
setTimeout
如何工作?
當您調用 setTimeout
函數時,您需要提供兩個參數:要執行的函數或代碼,以及以毫秒為單位的延遲。提供的函數/代碼將添加到隊列中,並在指定的延遲後,它將從隊列移動到調用堆棧以執行。
使用 setTimeout
的替代方法有哪些?
是的,有替代方法,例如 setInterval
,它會以指定的間隔重複執行函數,以及較新的 requestAnimationFrame
,它用於更流暢的動畫和更好的瀏覽器性能。
什麼時候不應該使用 setTimeout
?
setTimeout
是用於在 JavaScript 中調度異步代碼執行的有用工具,但在某些情況下它可能不是最佳選擇。對於精確的動畫或遊戲,您應該使用 requestAnimationFrame
。您不應該嵌套多個 setTimeout
調用;最好使用 Promise 或異步模式。 setTimeout
對小於 10 毫秒的延遲不准確;請考慮替代方案。如果您正在構建實時應用程序(如在線多人遊戲或金融交易平台),請選擇實時技術,如 WebSockets。大型 CPU 密集型任務可能會阻塞事件循環;如果需要,請使用 Web Workers。
我可以取消 setTimeout
操作嗎?
是的,您可以使用 clearTimeout
函數取消計劃的超時。它將 setTimeout
返回的超時 ID 作為參數。例如:const timeoutId = setTimeout(myFunction, 1000); clearTimeout(timeoutId);
setTimeout
和 setInterval
之間的區別是什麼?
setTimeout
將函數安排在指定的延遲後運行一次,而 setInterval
將函數安排在指定的間隔重複運行,直到它被取消或程序停止。
我可以使用 setTimeout
的最小延遲值是多少?
最小延遲值為 0,這意味著該函數安排在當前線程完成但處理任何掛起的事件之前執行。但是,計時器的實際粒度因不同的瀏覽器和環境而異。某些環境可能不支持小於 10 毫秒的延遲。
setTimeout
在 Node.js 中是什麼?
setTimeout
是 Node.js 的內置函數,用於將給定函數或代碼塊的執行延遲指定的毫秒數。
如何在 Node.js 中使用 setTimeout
?
您可以按如下方式使用 setTimeout
函數:setTimeout(callback, delay);
其中 callback
是您希望在指定的毫秒延遲後執行的函數。
在 Node.js 中使用 setTimeout
的最佳實踐有哪些?
一些最佳實踐包括使用命名函數作為回調函數,優雅地處理錯誤,並了解事件循環的行為以避免意外延遲或阻塞。此外,請考慮使用 setImmediate
在下一個事件循環週期中立即執行。
(請注意,由於輸入文本中包含 CodePen 的鏈接,我無法直接在輸出中呈現 CodePen 的內容。您需要訪問文中提供的鏈接來查看 CodePen 演示。)
以上是Settimeout JavaScript函數:指南示例的詳細內容。更多資訊請關注PHP中文網其他相關文章!