iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
Software Development

從零開始,在 coding 路上的 30 個為什麼?不對!是無數個為什麼!系列 第 6

Day 06 - 理解 JavaScript ,為什麼要知道一級函式、回呼函式?

  • 分享至 

  • xImage
  •  

上篇一個大談閉包的概念之後,今天來講一下函式相關的兩個重要概念
一級函式(First-Class Function)和回呼函式(Callback 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)機制。

回呼函數通常用於以下情況:

  1. 事件處理:當某個事件發生時,例如按下按鈕、網絡請求完成、定時器觸發等,系統會調用事先定義的回呼函數來處理事件。這使得事件處理代碼更加模組化和可維護。

  2. 非同步操作:在執行非同步操作(例如讀取文件、發送HTTP請求、處理用戶輸入等)時,回呼函數可用於處理操作完成後的回應或錯誤。這樣可以確保應用程序不會因等待操作完成而被阻塞。

  3. 泛型化設計:回呼函數允許您將特定行為以函數參數的形式傳遞給其他函數,從而實現更靈活的、可定制的行為。這種方法在許多庫和框架中被廣泛使用,例如 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("非同步操作正在進行中...");
    

    當我們執行這個代碼時,可以看到以下輸出順序:

    1. "開始執行非同步操作..."
    2. "非同步操作正在進行中..."(這是因為 setTimeout 函式會使操作非同步進行)
    3. 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 的通用函式,該函式遍歷陣列的每個元素,
    並將每個元素傳遞給回呼函式處理。

    定義兩個不同的回呼函式:

    1. printSquare 用於處理數字陣列,並計算每個數字的平方。
    2. toUpperCase 用於處理字串陣列,並將每個字串轉換為大寫。

    通過這種設計,我們可以輕鬆地處理不同類型的數據陣列,
    而不需要為每種數據類型創建不同的處理函式。


今天先建立基本的觀念,
我們下篇將提及回呼函式(Callback Function) 延伸概念 - Promise 以及 async/await!

是不是開始好奇 Promise 以及 async/await了呢!為什麼要理解他們?

下篇待續!

文章同步於個人部落格:Viiisit!(歡迎參觀 ୧ʕ•̀ᴥ•́ʔ୨)


上一篇
Day 05 - 理解 JavaScript ,為什麼要知道閉包(下)?
下一篇
Day 07 - 理解 JavaScript ,為什麼要知道 Promise 與 async/await?
系列文
從零開始,在 coding 路上的 30 個為什麼?不對!是無數個為什麼!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言