首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JavaScript setTimeout/clearTimeout 變數作用域陷阱與正確寫法

     編輯:程式設計綜合問答

錯誤代碼

function myFunction() {
    alert("click");
    var zh = setTimeout("myFunction()", 2000); // zh 為區域變數
}
function temp() {
    clearTimeout(zh); // 錯誤:zh 不在作用域內
}

問題分析

  • `var zh` 宣告在 `myFunction` 內部 → 作用域僅限該函式。
  • `temp()` 無法存取 `zh`,導致 `clearTimeout` 失效,定時器持續觸發。

正確寫法:提升變數至全域/模組作用域

var zh; // 全域或模組層級

function myFunction() {
    alert("click");
    zh = setTimeout(myFunction, 2000); // 直接傳函式參考,避免字串 eval
}
function temp() {
    clearTimeout(zh);
}

進階最佳實踐

  1. 避免字串參數:`setTimeout("myFunction()")` 等同 `eval`,效能差且難除錯。改用 `setTimeout(myFunction, 2000)`。
  2. 使用 IIFE/模組封裝,避免汙染全域:
const TimerModule = (() => {
    let timerId = null;
    return {
        start: () => { timerId = setTimeout(() => { TimerModule.start(); }, 2000); },
        stop: () => { clearTimeout(timerId); }
    };
})();

箭頭函式與 this 綁定

若在類別方法中使用 `setTimeout`,請用箭頭函式保持 `this` 指向:

class Counter {
    start() {
        this.timer = setTimeout(() => this.tick(), 1000);
    }
    tick() { console.log('tick'); }
}

總結

`setTimeout` 回傳的 ID 必須儲存在可被取消函式存取的作用域中。養成「宣告在外部、傳函式而非字串」的習慣,能避免 90% 的定時器 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved