Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Cách truyền tham số cho callback của setTimeout() trong JavaScript

Từ ES2015 (ES6), setTimeout() hỗ trợ truyền tham số trực tiếp cho hàm callback mà không cần closure hay bind.

Cú pháp chuẩn (ES6+)

setTimeout(callbackFunction, delayInMs, arg1, arg2, arg3, ...);
  • callbackFunction: Hàm sẽ được gọi sau delayInMs mili-giây.
  • delayInMs: Thời gian chờ (ms).
  • arg1, arg2...: Các tham số truyền cho callbackFunction.

Ví dụ

function greet(name, greeting = "Chào") {
    console.log(`${greeting} ${name}!`);
}

// Truyền tham số trực tiếp
setTimeout(greet, 1000, "An", "Xin chào"); // Sau 1s: "Xin chào An!"

// Với arrow function
setTimeout((msg, count) => console.log(`${msg} x${count}`), 2000, "Tick", 3); // "Tick x3"

Cách cũ (Trước ES6 / Cần tương thích IE cũ) - Dùng Closure / Bind

Cách 1: Anonymous function wrapper (Phổ biến nhất)

setTimeout(function() {
    greet("An", "Xin chào"); // Gọi hàm với tham số trong closure
}, 1000);

Cách 2: Function.prototype.bind()

setTimeout(greet.bind(null, "An", "Xin chào"), 1000);
// null = thisArg (không quan trọng ở đây)

Cách 3: IIFE (Immediately Invoked Function Expression) - ít dùng

(function(name, greeting) {
    setTimeout(function() {
        greet(name, greeting);
    }, 1000);
})("An", "Xin chào");

⚠️ LƯU Ý QUAN TRỌNG

  • Thứ tự tham số: setTimeout(fn, delay, ...args). Đừng nhầm setTimeout(fn, arg1, delay).
  • Giá trị tham số được "chụp" (captured) tại thời điểm gọi setTimeout, không phải khi callback chạy.
    for (var i = 0; i < 3; i++) {
        setTimeout(() => console.log(i), 100); // In ra: 3, 3, 3 (var function scoped)
    }
    // Sửa: dùng let (block scoped) hoặc truyền tham số
    for (let i = 0; i < 3; i++) {
        setTimeout(() => console.log(i), 100); // 0, 1, 2
    }
    // Hoặc truyền i làm tham số
    for (var i = 0; i < 3; i++) {
        setTimeout((i) => console.log(i), 100, i); // 0, 1, 2
    }
  • this bên trong callback: Mất ngữ cảnh (mặc định window hoặc undefined strict mode). Dùng arrow function hoặc .bind(this) nếu cần.
  • Trả về Timer ID: const timerId = setTimeout(...). Dùng clearTimeout(timerId) để hủy.

Ví dụ hoàn chỉnh (HTML)

<!DOCTYPE html>
<html>
<body>
<button onclick="startTimer()">Bắt đầu đếm 5s</button>
<p id="result"></p>
<script>
    function showMessage(msg, delay) {
        document.getElementById("result").innerText = `${msg} (sau ${delay/1000}s)`;
    }
    
    function startTimer() {
        const msg = "Đã hết 5 giây!";
        const delay = 5000;
        // Truyền tham số trực tiếp (ES6+)
        setTimeout(showMessage, delay, msg, delay);
    }
</script>
</body>
</html>

Tóm lại: Hãy dùng cú pháp ES6 chuẩn: setTimeout(fn, delay, arg1, arg2...). Đơn giản, rõ ràng, không cần closure/bind. Chú ý thứ tự tham số và capturing value.