箭頭函數(arrow functions)是什麼?常見語法解析

更新日期: 2023 年 10 月 17 日

箭頭函數是一種於 ECMAScript 6(也被稱為 ES2015)中新引入的函數語法。

在此之前,JavaScript 已經有了傳統的函數語法,那麼為什麼還需要一種新的函數語法呢?

箭頭函數的引入主要基於兩個目的:

  1. 為了提供一種更簡潔的函數寫法,尤其是在撰寫短小的回調函數時
  2. 為了解決 this 關鍵字在不同情境下容易造成混淆的問題

在傳統的函數語法中,this 的值經常不是我們所期望的,特別是在事件回調或其他異步操作中。

而箭頭函數解決了這個問題,它不綁定自己的 this,而是繼承外部作用域的 this

使得我們在寫程式碼時,可以更加直觀地理解 this 的行為。

此外,箭頭函數的語法也更加簡潔,使得程式碼更容易閱讀和維護。但同時,它也帶來了一些新的限制和特性,我們在後面的章節將會詳細介紹。

一般函數與箭頭函數的差異

箭頭函數 (arrow functions) 的語法,主要為了提供更簡短和更具表達性的寫法來定義函數。

以下是一些將一般函數縮寫為箭頭函數的情境:

單一參數,單一表達式

  • 一般函數:
function(x) { 
    return x * x; 
}
  • 箭頭函數:
x => x * x

多個參數,單一表達式

  • 一般函數:
function(x, y) { 
    return x + y; 
}
  • 箭頭函數:
(x, y) => x + y

單一參數,多條語句

  • 一般函數:
function(x) { 
    console.log(x); 
    return x * x; 
}
  • 箭頭函數:
x => { 
    console.log(x); 
    return x * x; 
}

無參數

  • 一般函數:
function() { 
    return 42; 
}
  • 箭頭函數:
() => 42

回傳物件

  • 一般函數:
function(x, y) { 
    return { 
        x: x, 
        y: y 
    }; 
}
  • 箭頭函數:
(x, y) => (
    {
        x: x, 
        y: y
    }
)

因為 {} 在箭頭函數中代表函數的區塊,所以當你想要直接回傳物件時,需要用括號包起來。

this 關鍵字的差異比較

方法調用

  • 一般函數:當一個函數作為物件的方法被調用時,this 會參考到那個物件。
const obj = {
  value: 'Hello',
  print: function() {
    console.log(this.value);
  }
};

obj.print();  // 輸出: Hello
  • 箭頭函數: 箭頭函數不會綁定自己的 this。它繼承了包含它的函數或全局作用域的 this。
const obj = {
  value: 'Hello',
  print: () => {
    console.log(this.value);
  }
};

obj.print();  // 輸出: undefined,因為箭頭函數繼承了全局作用域的 `this`

普通函數調用

  • 一般函數:
function traditionalFunction() {
  console.log(this);
}

traditionalFunction();  // 輸出: Window {...} 或 undefined(嚴格模式下)
  • 箭頭函數: 箭頭函數不會綁定自己的 this。它繼承了包含它的函數或全局作用域的 this。
const arrowFunction = () => {
  console.log(this);
};

arrowFunction();  // 輸出: Window {...} 或其它上下文,取決於箭頭函數是在哪裡被定義的

使用 new 調用

  • 一般函數:
function TraditionalClass() {
  this.value = 'Hello';
}

const instance = new TraditionalClass();
console.log(instance.value);  // 輸出: Hello
  • 箭頭函數: 事實上,您不能使用 new 關鍵字調用箭頭函數。這是因為箭頭函數不綁定其自己的 this,所以它也沒有 prototype 屬性,而 new 關鍵字正是依靠此屬性來建立一個新物件的。
const ArrowClass = () => {
  this.value = 'Hello';
};

// 下面的代碼將導致一個錯誤
// const arrowInstance = new ArrowClass();  

當然可以。以下是關於箭頭函數在 JavaScript 中的常見使用情境的內容:


箭頭函數常見的使用情境

箭頭函數由於其簡潔性和 this 繫結的特性,使其在多種情境下都非常受歡迎。

事件處理器和回調

由於事件處理器和回調函數,常常需要被定義為匿名函數

因此箭頭函數的簡短語法,非常適合此使用情境。

btn.addEventListener('click', (event) => {
    console.log("Button clicked!", event);
});

簡單的函數映射

箭頭函數使得基於一些條件,進行數據映射的操作更為簡潔

const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2);

短時間的延遲操作

使用 setTimeout setInterval 時,箭頭函數提供了簡短的語法。

setTimeout(() => {
    console.log("This will be logged after 2 seconds");
}, 2000);

當需要使用外部作用域的 this

例如,在一些涉及到操作 DOM 元素的情境,可能會需要在一個方法中使用外部作用域的 this

function Timer() {
    this.seconds = 0;
    setInterval(() => {
        this.seconds++;
        console.log(this.seconds + " seconds passed");
    }, 1000);
}

const timer = new Timer();

在上述例子中,如果使用傳統函數,this.seconds 將會引發錯誤,因為 this 會指向全局對象或者是 undefined(在嚴格模式下)。

當不需要特定的 this 繫結

有時,您可能不想有一個具體的 this 繫結,而只是想要一個純函數。

在這種情境下,箭頭函數是一個不錯的選擇。

const pureFunction = (x, y) => x + y;

結論

箭頭函數,自從其在 ES6 中的引入以來,已經成為 JavaScript 開發者工具箱中的一個不可或缺的工具。

其簡潔的語法不僅使代碼更易讀,還能提高編碼效率。

同時,它對 this 的特殊處理方式,解決了許多傳統匿名函數所面臨的問題。

但與此同時,也要注意箭頭函數並不適合所有情境。

例如,當需要一個具有自己 this 值的方法,或者當需要使用 arguments 物件時,傳統的函數表達式可能更為適合。

最終,無論是選擇使用箭頭函數還是傳統函數,最重要的是理解其背後的機制和語境。

Similar Posts