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

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

1. 箭頭函數名推斷

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

<code>(number=>number+1).name;//=>''/<code>

在調試會話或調用堆棧分析期間,匿名函數被標記為anonymous。不幸的是,anonymous程序不提供有關正在執行的代碼的任何線索。

這裡是執行匿名函數的代碼的調試會話:

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

右邊的調用堆棧由兩個標記為anonymous的函數組成,我們無法從這樣的調用堆棧信息中獲得任何有用的信息。

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

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

<code>constincreaseNumber=number=>number+1;increaseNumber.name;//=>'increaseNumber'/<code>

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

第1個實踐:

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

現在我們用使用名稱推斷的代碼檢查一個調試會話:

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

因為箭頭函數有名稱,所以調用堆棧提供了有關正在執行的代碼的更多信息。

  • handleButtonClick函數名稱表示發生了單擊事件
  • gainCounter增加一個計數器變量。

2.儘可能使用內聯方式

內聯函數是僅具有一個表達式的函數。我喜歡箭頭功能,可以編寫短內聯函數。

例如,不要使用箭頭函數的長形式:

<code>constarray=[1,2,3];array.map((number)=>{returnnumber*2;});/<code>

當箭頭函數只有一個表達式時,可以輕鬆地刪除大括號{}和return語句:

<code>constarray=[1,2,3];array.map(number=>number*2);/<code>

第2個實踐:

當函數只有一個表達式時,一個好的做法是使用內聯箭頭函數格式

3.胖箭頭和比較運算符

比較操作符>、=看起來類似於f胖箭頭=>(它定義了箭頭函數)。當在內聯箭頭函數中使用這些比較操作符時,會產生一些混淆。

例如我們定義一個使用<=操作符的箭頭函數

<code>constnegativeToZero=number=>number<=0?0:number;/<code>

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

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

<code>constnegativeToZero=number=>(number<=0?0:number);/<code>

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

<code>constnegativeToZero=number=>{returnnumber<=0?0:number;};/<code>

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

第3個實踐:

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

4.構造普通對象

在內聯箭頭函數中使用對象字面量會觸發語法錯誤:

<code>constarray=[1,2,3];//throwsSyntaxError!array.map(number=>{'number':number});/<code>

JS 認為花括號是代碼塊,而不是對象文字。

將對象字面量加上一對括號即可解決此問題:

<code>constarray=[1,2,3];//Works!array.map(number=>({'number':number}));/<code>

如果對象字面量有很多屬性,我們可以使用換行,同時仍然保持箭頭函數內聯

<code>constarray=[1,2,3];//Works!array.map(number=>({'number':number'propA':'valueA','propB':'valueB'}));/<code>

第4個實踐:

在內聯箭頭函數中使用對象時,把改對象包裝在一對括號中。

5.注意過多的嵌套

箭頭函數的語法很短,很好。但是,副作用是,當許多箭頭函數嵌套時,它可能是晦澀難懂。

我們考慮以下情況。單擊按鈕後,啟動對服務器的請求,響應準備就緒後,將各項記錄到控制檯:

<code>myButton.addEventListener('click',()=>{fetch('/items.json').then(response=>response.json());.then(json=>{json.forEach(item=>{console.log(item.name);});});});/<code>

這裡有三層箭頭函數的嵌套,需要花時間和精力來了解代碼的作用。

為了提高嵌套函數的可讀性,第一種方法是引入每個包含箭頭函數的變量,該變量應簡明地描述函數的功能。

<code>constreadItemsJson=json=>{json.forEach(item=>console.log(item.name));};consthandleButtonClick=()=>{fetch('/items.json').then(response=>response.json());.then(readItemsJson);};myButton.addEventListener('click',handleButtonClick);/<code> 

重構將箭頭函數提取到變量readItemsJson和handleButtonClick中。嵌套級別從3減少到2。現在,我們可以更輕鬆地瞭解腳本的功能。

更好的是,可以使用async/await語法重構整個函數,這是解決函數嵌套的一個很好的方法:

<code>consthandleButtonClick=async()=>{constresponse=awaitfetch('/items.json');constjson=awaitresponse.json();json.forEach(item=>console.log(item.name));};myButton.addEventListener('click',handleButtonClick);/<code>

第5個實踐:

避免箭頭函數過多的嵌套,好的做法是通過將箭頭函數提取為獨立函數,或者儘可能使用async/await語法。

6. 總結

JS中的箭頭函數是匿名的。為了使調試更高效,一個好的實踐是使用變量來保存箭頭函數,這允許JS 推斷函數名。

當函數主體具有一個表達式時,嵌入式箭頭函數非常方便。

操作符>、=看起來類似於胖箭頭=>,在內聯箭頭函數中使用這些操作符時必須小心。

對象字面量語法{prop:'value'}與代碼塊{}相似。因此,當將對象字面量放置在嵌入式箭頭函數中時,需要將其包裝在一對括號中:()=>({prop:'value'})。

最後,函數的過度嵌套模糊了代碼意圖。減少箭頭函數嵌套的一個好方法是將它們提取到變量中。或者,嘗試使用更好的特性,如async/await語法。

對於箭頭函數,你還有什麼建議,歡迎留言討論。


原文:https://dmitripavlutin.com/javascript-arrow-functions-best-practices/


分享到:


相關文章: