上篇一個大談閉包的概念之後,今天來講一下函式相關的兩個重要概念
一級函式(First-Class Function)和回呼函式(Callback 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)機制。
回呼函數通常用於以下情況:
事件處理:當某個事件發生時,例如按下按鈕、網絡請求完成、定時器觸發等,系統會調用事先定義的回呼函數來處理事件。這使得事件處理代碼更加模組化和可維護。
非同步操作:在執行非同步操作(例如讀取文件、發送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
函式會使操作非同步進行)泛型化設計
// 通用函式:遍歷數組並應用回呼函式
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
用於處理字串陣列,並將每個字串轉換為大寫。通過這種設計,我們可以輕鬆地處理不同類型的數據陣列,
而不需要為每種數據類型創建不同的處理函式。
今天先建立基本的觀念,
我們下篇將提及回呼函式(Callback Function) 延伸概念 - Promise 以及 async/await!
文章同步於個人部落格:Viiisit!(歡迎參觀 ୧ʕ•̀ᴥ•́ʔ୨)