回呼函數在處理異步任務、事件和高階函數時非常重要。能更好地編寫非同步程式,並優化代碼的結構和邏輯。
回呼函數是一個作為參數傳遞給另一個函數的函數,並且當某些條件滿足時或某個事件發生後被調用。回呼函數使我們能夠將某些代碼的執行推遲到特定時機,或用來處理某些需要延遲的操作。
範例:
function greet(name, callback) {
console.log("Hello, " + name);
callback();
}
function sayGoodbye() {
console.log("Goodbye!");
}
greet("Alice", sayGoodbye);
// 輸出:
// Hello, Alice
// Goodbye!
在這個例子中,sayGoodbye 作為回呼函數傳遞給 greet 函數,並在 greet 函數執行後被調用。
回呼函數可以是同步的,也可以是異步的。
範例(同步回呼):
let numbers = [1, 2, 3, 4];
numbers.forEach(function(num) {
console.log(num);
});
// 輸出:1, 2, 3, 4
範例(異步回呼):
console.log("Start");
setTimeout(function() {
console.log("This is the callback");
}, 2000);
console.log("End");
// 輸出順序:
// Start
// End
// This is the callback(延遲兩秒後顯示)
在這個例子中,setTimeout 是一個異步回呼,它在兩秒後才調用我們的回呼函數。
當多個回呼函數嵌套時,代碼結構會變得難以維護和閱讀,這種情況被稱為 回呼地獄(Callback Hell)。
範例:
setTimeout(function() {
console.log("Step 1");
setTimeout(function() {
console.log("Step 2");
setTimeout(function() {
console.log("Step 3");
}, 1000);
}, 1000);
}, 1000);
為了避免回呼地獄,JavaScript 引入了 Promises 和 async/await,使得異步代碼的結構更加清晰(這些主題我們會在後續的課程中介紹)。
回呼函數廣泛應用於各種異步操作中,例如:
範例(事件監聽器中的回呼函數):
document.getElementById("myButton").addEventListener("click", function() {
console.log("Button clicked!");
});
高階函數 是指接受一個或多個函數作為參數的函數,回呼函數在這裡經常使用。這讓代碼更加靈活,可以將具體邏輯與流程控制分離。
範例(map 使用回呼函數):
let numbers = [1, 2, 3, 4];
let squares = numbers.map(function(num) {
return num * num;
});
console.log(squares); // [1, 4, 9, 16]