JavaScript 的 Arrow function 概念
2023-09-17 19:42:47
#### Javascript 的 Arrow function ( 箭頭函數 ) 概念
1. `Arrow function` 的基本規則
2. `Arrow function` 的 `this` 作用域與一般函數不同
3. 沒有自己的 `arguments` 物件
4. 不能作為建構函數使用
---
#### 1. `Arrow function` 的基本規則
##### 1-1. 如果沒有任何參數 (Parameter) ,使用空括號 `()`
``` js
() => { console.log('沒有參數'); }
```
##### 1-2. 當你的箭頭函數只有一個參數 (Parameter) 時,括號 `()` 可以選擇要不要用。
``` js
x => { x * 2; }
// 或
(x) => { x * 2; }
```
##### 1-3. 如果箭頭函數的主體只有一行代碼,你可以選擇省略大括號 `{}`。
``` js
x => x * 2;
// 或
(x) => x * 2;
```
##### 1-4. 當你的箭頭函數有多個參數 (Parameter) 時, 必需使用括號 `()` 來包含所有的參數。
``` js
(x, y) => { console.log(x, y); }
```
##### 1-5. 當你的箭頭函數僅返回一個 `Javascript 物件` 時,會是無效的
``` js
number => { age: number }; // 嘗試返回一個物件
```
上述這段程式碼是無效的,因為 `JavaScript` 會將 `{ age: number }` 視為函數主體的一部分,而不是一個要返回的物件。
為了 "告訴" JavaScript 應該創建(並返回)一個物件,程式碼需要進行以下調整
``` js
number => ({ age: number }); // 將物件包裝在額外的括號中
```
使用額外的括號 `()` 告訴 JavaScript 這個箭頭函數應該返回一個物件 `{ age: number }`。
括號確保了 `JavaScript` 將大括號 `{}` 認為是物件字面量而非函數主體。
##### 1-6. 如果箭頭函數單行包含一個分號(通常是多個語句),必須使用大括號 `{}` 來封裝函數主體。
``` js
x => { console.log(x); return x * 2; }
```
---
#### 2. `Arrow function` 的 `this` 作用域與一般函數不同
#### 以下程式碼範例取自 Youtube 影片 - JavaScript ES6 Arrow Functions Tutorial
``` js
class Person {
constructor(name) {
this.name = name
}
printNameFunction() {
setTimeout(function() {
console.log('Function: ' + this.name)
},100)
}
printNameArrow() {
setTimeout(() => {
console.log('Arrow: ' + this.name)
}, 100)
}
}
let person = new Person('Bob')
person.printNameFunction()
// Function: undefined
person.printNameArrow()
// Arrow: Bob
```
##### 一般函數
一般函數會有自己的 `this` 作用域,
並且在這種情況下,`this` 會指向全域對象。
由於全域對象沒有 `name` 屬性,
所以輸出會是 `Function: undefined`。
##### 箭頭函數
箭頭函數不會創建自己的 `this` 作用域,
而是繼承了它被創建時的 `this` 作用域。
它繼承了 `printNameArrow` 方法的 `this` 作用域,
該作用域是 `Person` 類別的一個實例,
因此 `this.name` 是 `Bob`。
---
``` js
// 全域範圍
this.value = "global";
let exampleObj = {
value: "object",
regularFunction: function() {
console.log("一般函數 - this.value:", this.value);
},
arrowFunction: () => {
console.log("箭頭函數 - this.value:", this.value);
}
};
exampleObj.regularFunction(); // 輸出: "一般函數 - this.value: object"
exampleObj.arrowFunction(); // 輸出: "箭頭函數 - this.value: global"
```
##### 一般函數
在 `exampleObj` 內部使用一般函數時,`this` 會指向 `exampleObj` 本身。
所以,當我們調用 `regularFunction` 方法時,它會輸出 `object`,
因為 `this.value` 是指向 `exampleObj` 的 `value` 屬性。
##### 箭頭函數
使用箭頭函數時,`this` 會指向全域範圍的 `this`,而不是 `exampleObj`。
這是因為箭頭函數不會創建自己的 `this` 作用域,而是從它被創建的範圍中繼承 `this`,
在這個例子中, `this` 繼續往上尋找,直到找到全域環境的預設,
因此,當我們呼叫 `arrowFunction` 方法時,它會輸出 `global`,
因為 `this.value` 是指向全域的 `value` 屬性。
---
#### 3. 沒有自己的 `arguments` 物件
#### 以下程式碼範例取自 網路文章 5 Differences Between Arrow and Regular Functions
``` js
function myRegularFunction() {
const myArrowFunction = () => {
console.log(arguments);
}
myArrowFunction('c', 'd');
}
myRegularFunction('a', 'b');
// [Arguments] { '0': 'a', '1': 'b' }
```
當我們呼叫 `myRegularFunction` 並傳遞 `a` 和 `b` 作為參數時,
它創建了一個 `arguments` 物件,
該物件包含了傳遞給 `myRegularFunction` 的參數。
當我們在 `myRegularFunction` 內部呼叫 `myArrowFunction` 時,
由於箭頭函數沒有自己的 `arguments` 物件,
它會“繼承” 一般函數 `myRegularFunction` 的 `arguments` 物件。
因此,當我們在 `myArrowFunction` 內部印出 `arguments` 物件時,
它實際上是印出 `myRegularFunction` 的 `arguments` 物件,即包含 `a` 和 `b` 的物件。
---
#### 4. 不能作為建構函數使用
#### 以下程式碼範例取自 網路文章 5 Differences Between Arrow and Regular Functions
``` js
const Car = (color) => {
this.color = color;
};
const redCar = new Car('red');
// TypeError: Car is not a constructor
```
當使用箭頭函數來定義一個 `Car` 建構函數時,
由於箭頭函數不能創建自己的 `this` 作用域,
當你嘗試使用 `new` 關鍵字來創建一個新的 `Car` 實例時,
會出現 `TypeError: Car is not a constructor` 錯誤訊息,
因為 `Car` 不是一個建構函數。
---
#### 參考資料
[Udemy - lesson 22. More on the Arrow Function Syntax](https://www.udemy.com/course/react-the-complete-guide-incl-redux/learn/lecture/38345188#overview)
[MDN - Arrow function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
[5 Differences Between Arrow and Regular Functions](https://dmitripavlutin.com/differences-between-arrow-and-regular-functions/)
[鐵人賽:箭頭函式 (Arrow functions)](https://www.casper.tw/javascript/2017/12/21/javascript-es6-arrow-function/)
[什麼是箭頭函式 (Arrow Function)?跟一般的函式有什麼差別?](https://www.explainthis.io/zh-hant/swe/what-is-arrow-function)
[Youtube - JavaScript ES6:定義建構式 Constructor](https://www.youtube.com/watch?v=fzEQjnD2xKE&list=PL-g0fdC5RMboo-XNa2DzFvYg_9QWBIos6&ab_channel=%E5%BD%AD%E5%BD%AD%E7%9A%84%E8%AA%B2%E7%A8%8B)
[Youtube - JavaScript ES6 Arrow Functions Tutorial](https://www.youtube.com/watch?v=h33Srr5J9nY&ab_channel=WebDevSimplified)
[Reddit - Why are there so many different ways to write arrow functions?](https://www.reddit.com/r/learnjavascript/comments/16ij1ui/why_are_there_so_many_different_ways_to_write/?utm_source=share&utm_medium=web2x&context=3)
點擊複製文章連結
X