WeHelp
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)