編寫高質量可維護的代碼之優化邏輯判斷

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"if else、switch case 是日常開發中最常見的條件判斷語句,這種看似簡單的語句,當遇到複雜的業務場景時,如果處理不善,就會出現大量的邏輯嵌套,可讀性差並且難以擴展。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"編寫高質量可維護的代碼,我們先從最小處入手,一起來看看在前端開發過程中,可以從哪些方面來優化邏輯判斷?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面我們會分別從 JavaScript 語法和 React JSX 語法兩個方面來分享一些優化的技巧。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"JavaScript 語法篇"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"嵌套層級優化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function supply(fruit, quantity) {\n  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];\n  \/\/ 條件 1: 水果存在\n  if(fruit) {\n    \/\/ 條件 2: 屬於紅色水果\n    if(redFruits.includes(fruit)) {\n      console.log('紅色水果');\n      \/\/ 條件 3: 水果數量大於 10 個\n      if (quantity > 10) {\n        console.log('數量大於 10 個');\n      }\n    }\n  } else {\n    throw new Error('沒有水果啦!');\n  }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分析上面的條件判斷,存在三層 if 條件嵌套。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果提前 return 掉無效條件,將 if else 的多重嵌套層次減少到一層,更容易理解和維護。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function supply(fruit, quantity) {\n  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];\n  if(!fruit) throw new Error('沒有水果啦');     \/\/ 條件 1: 當 fruit 無效時,提前處理錯誤\n  if(!redFruits.includes(fruit)) return; \/\/ 條件 2: 當不是紅色水果時,提前 return\n    \n  console.log('紅色水果');\n    \n  \/\/ 條件 3: 水果數量大於 10 個\n  if (quantity > 10) {\n    console.log('數量大於 10 個');\n  }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"多條件分支的優化處理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當需要枚舉值處理不同的業務分支邏輯時,第一反應是寫下 if else ?我們來看一下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function pick(color) {\n  \/\/ 根據顏色選擇水果\n  if(color === 'red') {\n    return ['apple', 'strawberry']; \n  } else if (color === 'yellow') {\n    return ['banana', 'pineapple'];\n  } else if (color === 'purple') {\n    return ['grape', 'plum'];\n  } else {\n    return [];\n  }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上面的實現中:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"if else 分支太多"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"if else 更適合於條件區間判斷,而 switch case 更適合於具體枚舉值的分支判斷"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 switch case 優化上面的代碼後:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function pick(color) {\n  \/\/ 根據顏色選擇水果\n  switch (color) {\n    case 'red':\n      return ['apple', 'strawberry'];\n    case 'yellow':\n      return ['banana', 'pineapple'];\n    case 'purple':\n      return ['grape', 'plum'];\n    default:\n      return [];\n  }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"switch case 優化之後的代碼看上去格式整齊,思路很清晰,但還是很冗長。繼續優化:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"藉助 Object 的 { key: value } 結構,我們可以在 Object 中枚舉所有的情況,然後將 key 作爲索引,直接通過 Object.key 或者 Object[key] 來獲取內容"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const fruitColor = {                        \n  red: ['apple', 'strawberry'],\n  yellow: ['banana', 'pineapple'],\n  purple: ['grape', 'plum'],\n}\nfunction pick(color) {\n  return fruitColor[color] || [];\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 Map 數據結構,真正的 (key, value) 鍵值對結構;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const fruitColor = new Map()\n.set('red', ['apple', 'strawberry'])\n.set('yellow', ['banana', 'pineapple'])\n.set('purple', ['grape', 'plum']);\n\nfunction pick(color) {\n  return fruitColor.get(color) || [];\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"優化之後,代碼更簡潔、更容易擴展。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了更好的可讀性,還可以通過更加語義化的方式定義對象,然後使用 Array.filter 達到同樣的效果。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const fruits = [\n  { name: 'apple', color: 'red' }, \n  { name: 'strawberry', color: 'red' }, \n  { name: 'banana', color: 'yellow' }, \n  { name: 'pineapple', color: 'yellow' }, \n  { name: 'grape', color: 'purple' }, \n  { name: 'plum', color: 'purple' }\n];\n\nfunction pick(color) {\n  return fruits.filter(f => f.color == color);\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"使用數組新特性簡化邏輯判斷"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"巧妙的利用 ES6 中提供的數組新特性,也可以讓我們更輕鬆的處理邏輯判斷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"多條件判斷"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"編碼時遇到多個判斷條件時,本能的寫下下面的代碼(其實也是最能表達業務邏輯的面向過程編碼)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function judge(fruit) {\n  if (fruit === 'apple' || fruit === 'strawberry' || fruit === 'cherry' || fruit === 'cranberries' ) {\n    console.log('red');\n  }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是當 type 未來到 10 種甚至更多時, 我們只能繼續添加 || 來維護代碼麼?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"試試 "},{"type":"text","marks":[{"type":"strong"}],"text":"Array.includes"},{"type":"text","text":" ~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/\/ 將判斷條件抽取成一個數組\nconst redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];\nfunction judge(type) {\n  if (redFruits.includes(fruit)) {\n    console.log('red');\n  }\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"判斷數組中是否所有項都滿足某條件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const fruits = [\n  { name: 'apple', color: 'red' },\n  { name: 'banana', color: 'yellow' },\n  { name: 'grape', color: 'purple' }\n];\n\nfunction match() {\n  let isAllRed = true;\n\n  \/\/ 判斷條件:所有的水果都必須是紅色\n  for (let f of fruits) {\n    if (!isAllRed) break;\n    isAllRed = (f.color === 'red');\n  }\n\n  console.log(isAllRed); \/\/ false\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面的實現中,主要是爲了處理數組中的所有項都符合條件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 "},{"type":"text","marks":[{"type":"strong"}],"text":"Array.every"},{"type":"text","text":" 可以很容的實現這個邏輯:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const fruits = [\n  { name: 'apple', color: 'red' },\n  { name: 'banana', color: 'yellow' },\n  { name: 'grape', color: 'purple' }\n];\n\nfunction match() {\n  \/\/ 條件:所有水果都必須是紅色\n  const isAllRed = fruits.every(f => f.color == 'red');\n\n  console.log(isAllRed); \/\/ false\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"判斷數組中是否有某一項滿足條件"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Array.some"},{"type":"text","text":",它主要處理的場景是判斷數組中是否有一項滿足條件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果想知道是否有紅色水果,可以直接使用 "},{"type":"text","marks":[{"type":"strong"}],"text":"Array.some"},{"type":"text","text":" 方法:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const fruits = [\n    { name: 'apple', color: 'red' },\n    { name: 'banana', color: 'yellow' },\n    { name: 'grape', color: 'purple' }\n  ];\n\n\/\/ 條件:是否有紅色水果 \nconst isAnyRed = fruits.some(f => f.color == 'red');\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有許多其他數組新特性,比如 Array.find、Array.slice、Array.findIndex、Array.reduce、Array.splice 等,在實際場景中可以根據需要選擇使用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"函數默認值"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"使用默認參數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const buyFruit = (fruit,amount) => {\n  if(!fruit){\n   return\n  }\n  amount = amount || 1;\n  console.log(amount)\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們經常需要處理函數內部的一些參數默認值,上面的代碼大家都不陌生,使用函數的默認參數,可以很好的幫助處理這種場景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const buyFruit = (fruit,amount = 1) => {\n  if(!fruit){\n   return\n  }\n  console.log(amount,'amount')\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以通過 Babel 的轉譯來看一下默認參數是如何實現的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/41\/41ac047a1dd64faac8afe2bdfc6083bc.png","alt":"Image","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從上面的轉譯結果可以發現,只有參數爲 undefined 時纔會使用默認參數。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"測試的執行結果如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"buyFruit('apple','');  \/\/ amount\nbuyFruit('apple',null);  \/\/null amount\nbuyFruit('apple');  \/\/1 amount"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以使用默認參數的情況下,我們需要注意的是默認參數 "},{"type":"codeinline","content":[{"type":"text","text":"amount = 1"}]},{"type":"text","text":" 並不等同於 "},{"type":"codeinline","content":[{"type":"text","text":"amount || 1"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"使用解構與默認參數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當函數參數是對象時,我們可以使用解構結合默認參數來簡化邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Before:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const buyFruit = (fruit,amount) => {\n fruit = fruit || {};\n if(!fruit.name || !fruit.price){\n   return;\n }\n ...\n  amount = amount || 1;\n  console.log(amount)\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"After:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const buyFruit = ({ name,price }={},amount) => {\n  if(!name || !prices){\n    return;\n  }\n  console.log(amount)\n}\n"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"複雜數據解構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當處理比較簡的對象時,解構與默認參數的配合是非常好的,但在一些複雜的場景中,我們面臨的可能是更復雜的結構。"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const oneComplexObj = {\n firstLevel: {\n   secondLevel:[{\n    name:\"\",\n    price:\"\"\n   }]\n  }\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個時候如果再通過解構去獲取對象裏的值。"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const {\n  firstLevel:{\n    secondLevel:[{name,price]=[]\n  }={}\n} = oneComplexObj;              \n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可讀性就會比較差,而且需要考慮多層解構的默認值以及數據異常情況。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種情況下,如果項目中使用 lodash 庫,可以使用其中的 lodash\/get 方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"import lodashGet from 'lodash\/get';\n\nconst { name,price} = lodashGet(oneComplexObj,'firstLevel.secondLevel[0]',{});"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"策略模式優化分支邏輯處理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"策略模式:定義一系列的算法,把它們一個個封裝起來, 並且使它們可相互替換。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用場景:策略模式屬於對象行爲模式,當遇到具有相同行爲接口、行爲內部不同邏輯實現的實例對象時,可以採用策略模式;或者是一組對象可以根據需要動態的選擇幾種行爲中的某一種時,也可以採用策略模式;這裏以第二種情況作爲示例:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Before:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const TYPE = {\n  JUICE:'juice',\n  SALAD:'salad',\n  JAM:'jam'\n}\nfunction enjoy({type = TYPE.JUICE,fruits}){\n  if(!fruits || !fruits.length) {\n    console.log('請先採購水果!');\n    return;\n }\n  if(type === TYPE.JUICE) {\n    console.log('榨果汁中...');\n    return '果汁';\n  }\n  if(type === TYPE.SALAD) {\n    console.log('做沙拉中...');\n    return '拉沙';\n  }\n  if(type === TYPE.JAM) {\n    console.log('做果醬中...');\n    return '果醬';\n  }\n  return;\n}\n\nenjoy({type:'juice',fruits});"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用思路:定義策略對象封裝不同行爲、提供策略選擇接口,在不同的規則時調用相應的行爲。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"After:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const TYPE = {\n JUICE:'juice',\n SALAD:'salad',\n JAM:'jam'\n}\n\nconst strategies = {\n [TYPE.JUICE]: function(fruits){\n console.log('榨果汁中...');\n return '果汁';\n },\n [TYPE.SALAD]:function(fruits){\n console.log('做沙拉中...');\n return '沙拉';\n },\n [TYPE.JAM]:function(fruits){\n console.log('做果醬中...');\n return '果醬';\n },\n}\n\nfunction enjoy({type = TYPE.JUICE,fruits}) {\n if(!type) {\n console.log('請直接享用!');\n return;\n }\n if(!fruits || !fruits.length) {\n console.log('請先採購水果!');\n return;\n }\n return strategies[type](fruits);\n}\n\nenjoy({type:'juice',fruits});"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"框架篇之 React JSX 邏輯判斷優化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JSX 是一個看起來很像 XML 的 JavaScript 語法擴展。一般在 React 中使用 JSX 來描述界面信息,ReactDOM.render() 將 JSX 界面信息渲染到頁面上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 JSX 中支持 JavaScript 表達式,日常很常見的循環輸出子組件、三元表達式判斷、再複雜一些直接抽象出一個函數。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 JSX 中寫這麼多  JavaScript 表達式,整體代碼看起來會有點兒雜亂。試着優化一下!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"JSX-Control-Statements"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"JSX-Control-Statements"},{"type":"text","text":" (https:\/\/www.npmjs.com\/package\/jsx-control-statements) 是一個 Babel 插件,它擴展了 JSX 的能力,支持以標籤的形式處理條件判斷、循環。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"If 標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"標籤內容只有在 condition 爲 true 時纔會渲染,等價於最簡單的三元表達式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Before:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"{ condition() ? 'Hello World!' : null }   "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"After:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"Hello World!   "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:已被廢棄,複雜的條件判斷可以使用標籤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Choose 標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"標籤下包括至少一個標籤、可選的標籤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"標籤內容只有在 condition 爲 true 時纔會渲染,相當於一個 if 條件判斷分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"標籤則相當於最後的 else 分支。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Before:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"{ test1 ? IfBlock1 : test2 ? IfBlock2 : ElseBlock }"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"After:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\n  \n    IfBlock1\n  \n  \n    IfBlock2\n  \n  \n    ElseBlock\n  \n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"For 標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"標籤需要聲明 of、each 屬性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"of 接收的是可以使用迭代器訪問的對象。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"each 代表迭代器訪問時的當前指向元素。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Before:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"{\n  (this.props.items || []).map(item => {\n    return { item.title }\n  })\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"After:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\n  { item.title }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:標籤不能作爲根元素。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"With 標籤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"標籤提供變量傳參的功能。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Before:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"renderFoo = (foo) => {\n  return { foo };\n}\n\n\/\/ JSX 中表達式調用\n{\n  this.renderFoo(47)\n}\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"After:"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\n  { foo }\n\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用這幾種標籤優化代碼,可以減少  JSX 中存在的顯式 JavaScript 表達式,使我們的代碼看上去更簡潔,但是這些標籤封裝的能力,在編譯時需要轉換爲等價的 JavaScript 表達式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:具體 babel-plugin-jsx-control-statements 插件的使用見第三篇參考文章;Vue 框架已經通過指令的形式支持 v-if、v-else-if、v-else、v-show、slot 等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上我們總結了一些常見的邏輯判斷優化技巧。當然,編寫高質量可維護的代碼,除了邏輯判斷優化,還需要有清晰的註釋、含義明確的變量命名、合理的代碼結構拆分、邏輯分層解耦、以及更高層次的貼合業務的邏輯抽象等等,相信各位在這方面也有自己的一些心得,歡迎一起留言討論~"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頭圖:Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:米亞"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:https:\/\/mp.weixin.qq.com\/s\/S8nBOuu1W8RaXcdMN5U-yQ"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:編寫高質量可維護的代碼之優化邏輯判斷"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:政採雲前端團隊 - 微信公衆號 [ID:Zoo-Team]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"轉載:著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章