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 saudelayInMsmili-giây.delayInMs: Thời gian chờ (ms).arg1, arg2...: Các tham số truyền chocallbackFunction.
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ầmsetTimeout(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 } thisbên trong callback: Mất ngữ cảnh (mặc địnhwindowhoặcundefinedstrict mode). Dùng arrow function hoặc.bind(this)nếu cần.- Trả về Timer ID:
const timerId = setTimeout(...). DùngclearTimeout(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.