JavaScript] - First-Class Function & Callback Function
一級函式(FirstClass Function) 一級函式是指在程式語言中,函式被視為一種「第一級公民」,可以像其他數據類型(如整數、字符串)一樣被處理。 也就是說,函式可以被賦值給變數,作為函式的參數傳遞,以及作為函式的返回值。 一級函式的特點: 函式可以存儲在變數中。 函式可以作為另一個函式的...
一級函式(First-Class Function)
一級函式是指在程式語言中,函式被視為一種「第一級公民」,可以像其他數據類型(如整數、字符串)一樣被處理。 也就是說,函式可以被賦值給變數,作為函式的參數傳遞,以及作為函式的返回值。
一級函式的特點:
- 函式可以存儲在變數中。
- 函式可以作為另一個函式的參數傳遞。
- 函式可以作為另一個函式的返回值。
- 函式可以在運行時創建。
例如,以下是JavaScript中一級函式的例子:
// 函式賦值給變數
const greet = function(name) {
return `Hello, ${name}!`;
};
// 函式作為另一個函式的參數
function sayHello(greetingFunction, name) {
console.log(greetingFunction(name));
}
// 函式作為返回值
function createGreeter(greeting) {
return function(name) {
return `${greeting}, ${name}!`;
};
}
// 函式在運行時創建
const hello = createGreeter("Hi");
console.log(hello("Alice"));
回呼函式(Callback Function)
回呼函式是一種特殊的一級函式,他作為參數傳遞給另一個函式, 並且在特定條件滿足或事件發生時被調用。 通常用於事件處理、非同步操作和回呼(Callback)機制。
回呼函數通常用於以下情況:
事件處理:當某個事件發生時,例如按下按鈕、網絡請求完成、定時器觸發等,系統會調用事先定義的回呼函數來處理事件。這使得事件處理代碼更加模組化和可維護。
非同步操作:在執行非同步操作(例如讀取文件、發送HTTP請求、處理用戶輸入等)時,回呼函數可用於處理操作完成後的回應或錯誤。這樣可以確保應用程序不會因等待操作完成而被阻塞。
泛型化設計:回呼函數允許您將特定行為以函數參數的形式傳遞給其他函數,從而實現更靈活的、可定制的行為。這種方法在許多庫和框架中被廣泛使用,例如 JavaScript 中的 Array.map() 和 Array.filter()。
以下是JavaScript中回呼函式的例子:
-
事件處理 當你按下按鈕時,通常會觸發一個事件,例如 "click" 事件。 可以使用一個回呼函式,以便在按鈕被點擊時執行某些操作。
HTML(按鈕):
<!DOCTYPE html> <html> <head> <title>按鈕事件處理</title> </head> <body> <button id="myButton">點擊我</button> <script src="script.js"></script> </body> </html>JavaScript(script.js):
// 獲取按鈕元素 const myButton = document.getElementById('myButton'); // 定義回呼函式,當按鈕被點擊時執行 function buttonClickHandler() { alert('按鈕被點擊了!'); } // 將回呼函式註冊到按鈕的"click"事件上 myButton.addEventListener('click', buttonClickHandler);首先抓取 HTML 中的按鈕元素,然後定義了一個名為
buttonClickHandler的回呼函式。 最後,使用addEventListener方法將回呼函式註冊到按鈕的 'click' 事件上。 當按鈕被點擊時,buttonClickHandler函式就會被呼叫,彈出一個警告框,顯示按鈕被點擊了! 。 -
非同步處理 使用
setTimeout函式模擬一個非同步操作,並使用回呼函式來處理操作完成後的結果。function simulateAsyncOperation(callback) { setTimeout(function() { const data = "這是非同步操作的結果"; callback(null, data); // 呼叫回呼函式,傳遞結果或錯誤 }, 2000); // 假設操作需要2秒完成 } // 定義一個回呼函式來處理非同步操作的結果 function handleAsyncResult(error, result) { if (error) { console.error("出現錯誤:" + error); } else { console.log("非同步操作成功,結果為:" + result); } } console.log("開始執行非同步操作..."); // 呼叫非同步操作函式,並傳遞回呼函式 simulateAsyncOperation(handleAsyncResult); console.log("非同步操作正在進行中...");當我們執行這個代碼時,可以看到以下輸出順序:
- "開始執行非同步操作..."
- "非同步操作正在進行中..."(這是因為
setTimeout函式會使操作非同步進行) - 2 秒後,"非同步操作成功,結果為:這是非同步操作的結果"
-
泛型化設計
// 通用函式:遍歷數組並應用回呼函式 function processArray(array, callback) { for (let i = 0; i < array.length; i++) { callback(array[i]); } } // 定義一個回呼函式,用於打印數字的平方 function printSquare(num) { console.log(num * num); } // 定義一個回呼函式,用於將字串轉換為大寫 function toUpperCase(str) { console.log(str.toUpperCase()); } // 數字陣列 const numbers = [1, 2, 3, 4, 5]; console.log("處理數字陣列:"); processArray(numbers, printSquare); // 使用 printSquare 回呼函式處理 // 字串陣列 const strings = ["apple", "banana", "cherry"]; console.log("處理字串陣列:"); processArray(strings, toUpperCase); // 使用 toUpperCase 回呼函式處理我們有一個名為
processArray的通用函式,該函式遍歷陣列的每個元素, 並將每個元素傳遞給回呼函式處理。定義兩個不同的回呼函式:
printSquare用於處理數字陣列,並計算每個數字的平方。toUpperCase用於處理字串陣列,並將每個字串轉換為大寫。
通過這種設計,我們可以輕鬆地處理不同類型的數據陣列, 而不需要為每種數據類型創建不同的處理函式。