之前在寫一個 React 專案時,我發現我用了太多的 if else
,於是在重構程式碼的時候,我嘗試刪除了大量的 if else
,最終發現程式碼變簡潔了,可讀性更高了。所以如果你的程式碼中也出現了大量的if else
,說明你的程式碼出問題了。
在 code reviews 的時候,我會關注下面幾個問題:
- 一個函式幹了幾件事情,是否需要分離,讓一個函式只幹一件事?
- 檢查函式中的
if else
,看是否可以替換它。 - 怎麼改善可讀性?比如用設計模式替換
if else
(我最喜歡用物件對映模式)。 - 如果必須使用
if else
,那麼刪除else
,保留if
,並返回預設值。
接下來我會舉幾個例子來展示如何替代 if else
。
刪除 else
重構前:
if (red) {
return false;
} else if (blue) {
return false;
} else {
return true;
}
複製程式碼
重構後:
if (red || blue) {
return false;
}
return true;
複製程式碼
重構後的程式碼可以很直觀的看到預設返回值,更簡潔易讀。
組合函式
當你發現一個函式做了很多件事情,那麼用組合函式可以很好的處理它。把函式分離成多個函式,然後把它們組合起來。
舉個例子:我們來建立一個可以生成包含皮毛和爪子的雌性動物的函式
import { flow } from 'lodash';
const femaleAnimalsWithFurAndClaws = flow(
getFemales,
getAnimalsWithFur,
getAnimalsWithClaws,
)(animals);
複製程式碼
程式碼處理成這樣,我們可以很輕鬆的重用裡面的函式(比如 getFemales)。
物件對映模式
這是我最喜歡的設計模式之一,可使用的場景也很多,不管是在前端還是後端編碼中都可以用。它帶來的好處就是,讓程式碼簡潔易讀。每次我用這種設計模式的時候,我都覺得我的程式碼不是程式碼,而是說明書(^_^)。
來看一個簡單的例子:
const colors = {
red: false,
blue: false,
'default': true,
};
const colorMapper = color => colors[color] || colors['default'];
const color = colorMapper(item.color);
複製程式碼
它由兩個部分組成,一個儲存返回結果的物件和一個對映函式。
我們設定了預設值,即使在呼叫 colorMapper 函式的時候,沒有傳入引數,或者傳入了錯誤引數,都不會報錯,並返回預設值。後期維護的時候,我們也可以很輕鬆的新增其他的顏色。
當然我們也可以用 switch
來達到同樣的效果,就我個人而言並不喜歡這種語法,還是物件對映的方式更簡潔優美(^_^)。
物件對映模式 + React
用 React 寫專案,才是物件對映模式大放異彩的時候。當我們渲染很多不同的元件時,我們需要在程式碼中寫大量的條件判斷。如果用物件對映模式,問題就變得簡單了。看下面的例子:
首先資料看起來是這樣的,每個物件都有一個 type
和 content
鍵。
const items = [{
type: ‘hero’,
content: : {…},
}, {
type: 'text',
content: : {…},
}, {
type: 'image_and_text',
content: : {…},
}, {
type: 'text',
content: : {…},
}, {
type: 'call_to_action',
content: : {…},
}];
複製程式碼
然後寫一個對映函式,每個鍵表示一個 React 元件,每個元件都有 prop
,就上面資料中的 content
。
const components = {
hero: HeroComponent,
text: TextComponent,
image_and_text: ImageAndTextComponent,
call_to_action: CallToActionComponent,
'default': null,
};
const componentMapper = type =>
components[type] || components['default'];
複製程式碼
接下來就可以在專案中用了:
import react from ‘react’;
const RenderItems = props => {
const componentList = props.items((item, index) => {
const Component = componentMapper(item.type);
return <Component content={item.content} />
};
return (
<div>
{componentList}
</div>
)
};
複製程式碼