編寫高質量箭頭函式的5個最佳做法

前端小智發表於2020-02-14

作者:Dmitri Pavlutin

譯者:前端小智

來源:dmitripavlutin.com

點贊再看,養成習慣

本文 GitHub github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了很多我的文件,和教程資料。歡迎Star和完善,大家面試可以參照考點複習,希望我們一起有點東西。

箭頭功能值得流行。 它的語法簡潔明瞭,使用詞法繫結繫結 this,它非常適合作為回撥。在本文中,通過了解決學習5個最佳實踐,以便我們可以從中學習更多箭頭函式的知識,並從它身上獲得更多的好處。

1. 箭頭函式名推斷

JS 中的箭頭函式是匿名(anonymous)的:函式的name屬性是''

( number => number + 1 ).name; // => ''
複製程式碼

在除錯會話或呼叫堆疊分析期間,匿名函式被標記為anonymous。 不幸的是,anonymous程式不提供有關正在執行的程式碼的任何線索。

這裡是執行匿名函式的程式碼的除錯會話:

編寫高質量箭頭函式的5個最佳做法

右邊的呼叫堆疊由兩個標記為anonymous的函式組成,我們無法從這樣的呼叫堆疊資訊中獲得任何有用的資訊。

幸運的是,函式名推斷(ES2015的功能)可以在某些條件下檢測到函式名稱。 名稱推斷的思想是JS 可以從其語法位置確定箭頭函式名稱: 從儲存函式物件的變數名稱中獲取。

我們來看看函式名稱推斷的工作原理:

const increaseNumber = number => number + 1;

increaseNumber.name; // => 'increaseNumber'
複製程式碼

因為變數increaseNumber儲存了箭頭函式,所以 JS 決定使用increaseNumber作為該函式的名稱。因此,箭頭函式的名稱為 'increaseNumber'

第1個實踐:

一個好的做法是使用函式名稱推斷來命名箭頭函式。

現在我們用使用名稱推斷的程式碼檢查一個除錯會話:

編寫高質量箭頭函式的5個最佳做法

因為箭頭函式有名稱,所以呼叫堆疊提供了有關正在執行的程式碼的更多資訊。

  • 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;
複製程式碼

同一行上的兩個符號=><=的存在會引起誤解。

為了清楚地將胖箭頭與比較操作符區分開,我們可以使用圓括號:

const negativeToZero = number => (number <= 0 ? 0 : number);
複製程式碼

第二個選項是使用更長的形式來定義箭頭函式:

const negativeToZero = number => {
  return number <= 0 ? 0 : number;
};
複製程式碼

這些重構消除了胖箭頭符號和比較操作符之間的混淆。

第3個實踐:

如果箭頭函式包含操作符><<=>=,一個好的做法是將表示式包裝成一對括號,或者故意使用更長的箭頭函式形式。

4.構造普通物件

在內聯箭頭函式中使用物件字面量會觸發語法錯誤:

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);
複製程式碼

重構將箭頭函式提取到變數readItemsJsonhandleButtonClick中。 巢狀級別從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,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:dmitripavlutin.com/javascript-…


交流

文章每週持續更新,可以微信搜尋「 大遷世界 」第一時間閱讀和催更(比部落格早一到兩篇喲),本文 GitHub github.com/qq449245884… 已經收錄,整理了很多我的文件,歡迎Star和完善,大家面試可以參照考點複習,另外關注公眾號,後臺回覆福利,即可看到福利,你懂的。

編寫高質量箭頭函式的5個最佳做法

相關文章