編寫高質量箭頭函數的5個優(yōu)秀做法
箭頭功能值得流行。 它的語法簡潔明了,使用詞法綁定綁定 this,它非常適合作為回調。在本文中,通過了解決學習5個最佳實踐,以便我們可以從中學習更多箭頭函數的知識,并從它身上獲得更多的好處。
1. 箭頭函數名推斷
JS 中的箭頭函數是 匿名(anonymous)
的:函數的 name
屬性是 ''
。
- ( number => number + 1 ).name; // => ''
在調試會話或調用堆棧分析期間,匿名函數被標記為 anonymous
。 不幸的是, anonymous
程序不提供有關正在執(zhí)行的代碼的任何線索。
這里是執(zhí)行匿名函數的代碼的調試會話:
右邊的調用堆棧由兩個標記為 anonymous
的函數組成,我們無法從這樣的調用堆棧信息中獲得任何有用的信息。
幸運的是,函數名推斷(ES2015的功能)可以在某些條件下檢測到函數名稱。 名稱推斷的思想是JS 可以從其語法位置確定箭頭函數名稱: 從保存函數對象的變量名稱中獲取。
我們來看看函數名稱推斷的工作原理:
- const increaseNumber = number => number + 1;
- increaseNumber.name; // => 'increaseNumber'
因為變量 increaseNumber
保存了箭頭函數,所以 JS 決定使用 increaseNumber
作為該函數的名稱。因此,箭頭函數的名稱為 'increaseNumber'
。
第1個實踐:
一個好的做法是使用函數名稱推斷來命名箭頭函數。
現在我們用使用名稱推斷的代碼檢查一個調試會話:
因為箭頭函數有名稱,所以調用堆棧提供了有關正在執(zhí)行的代碼的更多信息。
- handleButtonClick
- gainCounter
2.盡可能使用內聯方式
內聯函數是僅具有一個表達式的函數。 我喜歡箭頭功能,可以編寫短內聯函數。
例如,不要使用箭頭函數的長形式:
- const array = [1, 2, 3];
- array.map((number) => {
- return number * 2;
- });
當箭頭函數只有一個表達式時,可以輕松地刪除大括號 {}
和 return
語句:
- const array = [1, 2, 3];
- array.map(number => number * 2);
第2個實踐:
當函數只有一個表達式時,一個好的做法是使用內聯箭頭函數格式
3.胖箭頭和比較運算符
比較操作符 >
、 <
、 <=
和 >=
看起來類似于f胖箭頭 =>
(它定義了箭頭函數)。當在內聯箭頭函數中使用這些比較操作符時,會產生一些混淆。
例如我們定義一個使用 <=
操作符的箭頭函數
- const negativeToZero = number => number <= 0 ? 0 : number;
同一行上的兩個符號 =>
和 <=
的存在會引起誤解。
為了清楚地將胖箭頭與比較操作符區(qū)分開,我們可以使用圓括號:
- const negativeToZero = number => (number <= 0 ? 0 : number);
第二個選項是使用更長的形式來定義箭頭函數:
- const negativeToZero = number => {
- return number <= 0 ? 0 : number;
- };
這些重構消除了胖箭頭符號和比較操作符之間的混淆。
第3個實踐:
如果箭頭函數包含操作符 >
、 <
、 <=
和 >=
,一個好的做法是將表達式包裝成一對括號,或者故意使用更長的箭頭函數形式。
4.構造普通對象
在內聯箭頭函數中使用對象字面量會觸發(fā)語法錯誤:
- const array = [1, 2, 3];
- // throws SyntaxError!
- array.map(number => { 'number': number });
JS 認為花括號是代碼塊,而不是對象文字。
將對象字面量加上一對括號即可解決此問題:
- const array = [1, 2, 3];
- // Works!
- array.map(number => ({ 'number': number }));
如果對象字面量有很多屬性,我們可以使用換行,同時仍然保持箭頭函數內聯
- const array = [1, 2, 3];
- // Works!
- array.map(number => ({
- 'number': number
- 'propA': 'value A',
- 'propB': 'value B'
- }));
第4個實踐:
在內聯箭頭函數中使用對象時,把改對象包裝在一對括號中。
5.注意過多的嵌套
箭頭函數的語法很短,很好。 但是,副作用是,當許多箭頭函數嵌套時,它可能是晦澀難懂。
我們考慮以下情況。 單擊按鈕后,啟動對服務器的請求,響應準備就緒后,將各項記錄到控制臺:
- myButton.addEventListener('click', () => {
- fetch('/items.json')
- .then(response => response.json());
- .then(json => {
- json.forEach(item => {
- console.log(item.name);
- });
- });
- });
這里有三層箭頭函數的嵌套,需要花時間和精力來了解代碼的作用。
為了提高嵌套函數的可讀性,第一種方法是引入每個包含箭頭函數的變量,該變量應簡明地描述函數的功能。
- const readItemsJson = json => {
- json.forEach(item => console.log(item.name));
- };
- const handleButtonClick = () => {
- fetch('/items.json')
- .then(response => response.json());
- .then(readItemsJson);
- };
- myButton.addEventListener('click', handleButtonClick);
重構將箭頭函數提取到變量 readItemsJson
和 handleButtonClick
中。 嵌套級別從3減少到2。現在,我們可以更輕松地了解腳本的功能。
更好的是,可以使用 async/await
語法重構整個函數,這是解決函數嵌套的一個很好的方法:
- const handleButtonClick = async () => {
- const response = await fetch('/items.json');
- const json = await response.json();
- json.forEach(item => console.log(item.name));
- };
- myButton.addEventListener('click', handleButtonClick);
第5個實踐:
避免箭頭函數過多的嵌套,好的做法是通過將箭頭函數提取為獨立函數,或者盡可能使用 async/await
語法。
6. 總結
JS中的箭頭函數是匿名的。為了使調試更高效,一個好的實踐是使用變量來保存箭頭函數,這允許JS 推斷函數名。
當函數主體具有一個表達式時,嵌入式箭頭函數非常方便。
操作符 >
、 <
、 <=
和>=看起來類似于胖箭頭 =>
,在內聯箭頭函數中使用這些操作符時必須小心。
對象字面量語法 {prop:'value'}
與代碼塊 {}
相似。 因此,當將對象字面量放置在嵌入式箭頭函數中時,需要將其包裝在一對括號中: ()=>({prop:'value'})
。
async/await
語法。對于箭頭函數,你還有什么建議,歡迎留言討論。
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行l(wèi)og 調試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug 。
原文: https://dmitripavlutin.com/ja...