提煉函數做爲代碼重構中常見的方式之一,是應該最被重視的。但咱們程序中某些片斷能夠被獨立出來,那麼就建議將這部分獨立爲一個函數,經過命名以及解耦的方式這端代碼發揮更大的價值。最被提倡的函數是純函數。javascript
提煉函數的主要優勢:java
舉例:拼接用戶信息算法
async getUser = function() {
var user = await Api.getUser() ;
var {name, age, sex} = user ;
var userInfo = `${name}:${age}歲,性別:${sex}`;
}
// 提煉函數 ,提煉以後的好處是與拼接用戶信息的需求都獨立爲函數,函數對外只依賴user對象
async getUser = function() {
var user = await Api.getUser() ;
var userInfo = gerUserInfoMsg(user);
}
function gerUserInfoMsg (user){
var {name, age, sex} = user ;
return `${name}:${age}歲,性別:${sex}`;
}
複製代碼
若是一個代碼段有大量的重複代碼,尤爲常見的是分支語句中有重複代碼,有必要進行合併去重。設計模式
好比下面的案例:重複調用setState有必定規律的屬性賦值,重複的判斷一些type類型均可以進行合併去重。架構
setDropDownVisible = (type) => {
if(type === 'vaild'){
this.setState({
vaildDropdown: true
})
}
if(type === 'sex'){
this.setState({
sexDropdown: true
})
}
if(type === 'age'){
this.setState({
ageDropdown: true
})
}
}
// 優化後
setDropDownVisible = (type) => {
const typeArr = ['vaild', 'sex', 'age'];
if(typeArr.includes(type)){
this.setState({
[`${type}Dropdown`]: true
})
return
}
console.warning(type + 'is not in stand type');
}
複製代碼
在複雜度較高的程序中會存在不少看似很複雜的條件判斷造成分支語句以及與這個條件有關的封裝代碼段,若是某個條件構成良好的準則,能夠將判斷條件進行封裝,讓邏輯更加清晰。async
function getPrice(price,month){
if(!month) return ;
if(month >= 6 && month <= 9 ) {
return price * 0.8
}
}
// 其中 month >= 6 && month <= 9的代碼含義是判斷是否處於夏季,提煉函數
function isSummer(month){
return month >= 6 && month <= 9
}
function getPrice(price,month){
if(!month) return ;
if(isSummer(month)) {
return price * 0.8
}
}
複製代碼
看似簡單的循環能夠幫咱們處理不少重複而簡單的代碼以及過程,也可讓維護更加簡單,讓代碼更有規律。函數
render(){
return (
<select> <option value="1">第一季度</option> <option value="2">第二季度</option> <option value="3">第三季度</option> <option value="4">第四季度</option> </select>
)
}
// 上面的option明顯的能夠用循環的方式來進行
render(){
const seasonArr = [
{
value: 1,
label: '第一季度'
},
{
value: 2,
label: '第二季度'
},
{
value: 3,
label: '第三季度'
},
{
value: 4,
label: '第四季度'
},
];
return (
<select> {seasonArr.map(item) => (<option value={value} key={value}>{label}</option>)} </select>
)
}
複製代碼
在咱們書寫大多數函數的時候,不少人喜歡用一個返回關鍵變量控制結果,而後最後返回結果。其實這樣的書寫能夠簡化爲當獲得結果時當即返回,一則邏輯更加清晰,減小了不少嵌套 ;二則 函數的運行效率更高。性能
function judgeAge(age){
var judgeResult = '';
if(age < 18){
judgeResult = '未成年'
} else if(age < 30){
judgeResult = '青年'
} else if(age < 50){
judgeResult = '中年'
} else if(age < 100){
judgeResult = '老年'
}
return judgeResult;
}
// 改造後,斷定結果收集,符合任何一個條件,立刻返回跳出函數
function judgeAge(age){
var judgeResultArr = ['未成年', '青年','中年', '老年'];
if(age < 18){
return judgeResultArr[0]
}
if(age < 30){
return judgeResultArr[1]
}
if(age < 50){
return judgeResultArr[2]
}
if(age < 100){
return judgeResultArr[3]
}
}
複製代碼
function person(age, sex, age, edu){
}
// 參數改造後
function person(personObj){
}
var personObj = {
name:"zhangsan",
sex: 'male',
age: 12,
}
var zhangsan = new Person(personObj);
複製代碼
須要將代碼進行解析,是否有些參數是存在關聯的,可代替的,好比咱們須要畫布設置一個正方形的div色塊,須要傳入寬高以及面積。優化
而通過分析以後,咱們先肯定需求,若是隻須要畫正方形,那麼只須要傳入寬度,高度等於寬度不用傳,面積也能夠經過計算得知。ui
function drawSquare(width, height, s){
}
function drawSquare(width){
let height = width;
let s = width * height;
}
複製代碼
三目運算能夠解決的問題,須要返回一個結果值,而且沒有過多的邏輯判斷。若是你是須要邏輯與運算、或運算,能夠直接採用熔斷寫法。
好比下面的,let sex = sex ? sex : 'male'
, 能夠用let sex = sex || 'male'
,那麼就能夠 更簡單; 同理,若是你但願基於存在的狀況下去判斷執行語句,不然不執行邏輯 , 好比jsx語法中: {isAble ? <button/> : null}
,直接寫成,{isAble && <button/>}
let patch = fs ? path ? fs(path) : fs('xxx') : null
// 這種多餘兩層的邏輯判斷更建議你們寫if/else 實現
if(fs) {
if(path){
} else {
}
} else {
}
複製代碼
具體參照鏈的設計模式,作法很簡單,在方法執行完成後返回this,就能夠實現鏈式的不斷調用執行方法,能夠簡化大量的代碼。
主要是將複雜的方法或者算法或者具備典型特徵的對象進行肢解,讓其以組合的方式進行設計,不但進行了解耦,並且可讓總體的架構可維護性更強。
由於for循環,尤爲多層嵌套循環會佔用的大量的內存以及運行時間,若是在函數獲得指望結果的時候,那麼就建議及時的跳出循環,避免性能的浪費。好比咱們要寫一個Array.prototype.includes方法.
Array.prototype.includes = function (arr, key){
if(!Array.isArray(arr)) return false ;
let isInclude = false;
for(let i = 0;len = arr.length;i<len;i++){
if(key === arr[i]){
isInclude = true;
break;
}
}
return isInclude;
}
複製代碼