原文:JavaScript 復(fù)雜判斷的更優(yōu)雅寫(xiě)法
正好看到這篇文章時(shí),我也思考過(guò)幾次如何簡(jiǎn)化 if else的問(wèn)題.
然后我就跟著這個(gè)又打了一遍.
他寫(xiě)的思路很清晰, 邏輯也很清晰.
后面的字符串的處理,也很腦洞大開(kāi).
不過(guò)我跟著大概打完一遍之后,
感覺(jué)還是有很多地方有疑問(wèn).
怎么說(shuō)呢, 就好像, 我隱隱約約摸到了,看到了什么東西,
但我無(wú)法用正確的概念體系去表達(dá),
而因?yàn)槲覜](méi)有這種明確的概念語(yǔ)言體系,
我想掌握起來(lái),甚至記憶起來(lái)也感覺(jué)很費(fèi)勁?
首先是這整片下來(lái),是存在一個(gè)前提的,或者適用的范圍是這樣的.
如果稍微細(xì)心一點(diǎn)就會(huì)發(fā)現(xiàn).
所有的 if 里的條件 都是 ==
而如果 == 的原始值, 也就是 布爾值, 數(shù)字,字符串,
則非常適合用 對(duì)象的形式.
因?yàn)閷?duì)象天然鍵值對(duì)形式,就包含了這種 == 的 if else
第二個(gè)問(wèn)題是維度問(wèn)題.
(天吶,我覺(jué)得科班出身的優(yōu)勢(shì)可能是擁有健全的概念體系,我特么不知道詞是不是合適啊)
我們以對(duì)象為例.
儲(chǔ)存對(duì)象有縱向維度,和橫向維度.
縱向
obj = {
"peter" : {
"a" : "aa"
},
"mike" : {
"a" : "bb"
}
}
特點(diǎn)是,直接通過(guò)索引我們就可以找到值,不需要去遍歷,判斷
也許語(yǔ)義化可以更好?
橫向
obj = {
0 : {
master : "peter",
type : "a",
value : "aa"
},
1 : {
master : "mike",
type : "a",
value : "bb"
},
}
首先這種情況用數(shù)組可能更好表達(dá).
特點(diǎn)是,需要遍歷,
相比上縱向的層級(jí)較少?
而且從某種角度來(lái)講,數(shù)據(jù)更加的豐富,
可操作的返回更多? 可擴(kuò)展性更強(qiáng)?
問(wèn)題在于, 無(wú)論是縱向還是橫向,
我們都可以認(rèn)為,多元條件時(shí),想要正確的鎖定,都需要增加維度.
要么是橫向?要么是縱向?
但這里并非是二選一, 可選的范圍很廣,
不同的數(shù)據(jù)放置方式,
可擴(kuò)展性不同,
最終調(diào)用的方式上應(yīng)該也會(huì)有所差異吧?
我暫時(shí)經(jīng)驗(yàn)少, 到底誰(shuí)跟誰(shuí)應(yīng)該在一起,
是根據(jù)數(shù)據(jù)的來(lái)源定?
還是根據(jù)數(shù)據(jù)的語(yǔ)義來(lái)定? (面向?qū)ο?)
還是根據(jù)別的什么? 常量和變量?
如果從語(yǔ)義上, 有一些維度比另一些維度要高,
那么就要體現(xiàn)出來(lái)?
比如 master 的維度,似乎比 type的維度高?
(在這個(gè)例子上完全也可以讓type的維度更高?)
怎么判斷誰(shuí)的維度更高? 根據(jù)必須有 a 才能有b 的原則?
當(dāng)然這些我現(xiàn)在是不清楚的.
甚至我可能都問(wèn)不出正確的問(wèn)題.
obj = {
"peter" : {
type : "a",
value : "aaa"
} ,
或者
0 : [{master : "mike",type : "a"},"aa"]
}
第三個(gè)問(wèn)題是,
我們?cè)诘谝粋€(gè)問(wèn)題中說(shuō)到,
本文的適用情況基本上都是== 情況.
那么其他類(lèi)型的條件 能否轉(zhuǎn)化成 == 這種情況?
或者更直接一點(diǎn), 我們是否可以轉(zhuǎn)換成一個(gè)字符串?
其實(shí)這里是有兩種思路的.
第一種思路
我們首先回到if 的形式上
(a,b) // 參數(shù)入口
if (conditionA && conditionB) {
function a
function b
}
從結(jié)果上看應(yīng)該是
根據(jù) condition 和 參數(shù)(a,b) 確定 找到 相應(yīng)的 function
假設(shè)各種funciton 都放在了一個(gè)個(gè)對(duì)象里, 并且有 索引可以找到.
那么 condition 就需要 返回索引
但condition 一般是要返回布爾值, 要么false 要么 true
我們可以轉(zhuǎn)換成 根據(jù) 參數(shù) a,b 和 false true 返回一個(gè)或多個(gè)字符串?
回想策略模式,
是用一個(gè)數(shù)組,或者對(duì)象, 把所有的condition都擱置起來(lái).
不同的參數(shù)值 + 不同的condition 返回不同的 字符串(或者布爾值),
根據(jù)多個(gè)condition 返回的值(字符串或布爾值),調(diào)用相應(yīng)的函數(shù),
或者生成相應(yīng)的執(zhí)行函數(shù)放入某個(gè)數(shù)組里.
第四個(gè)問(wèn)題是,
也就是我抄寫(xiě)的這篇博文打開(kāi)我腦洞的地方.
從結(jié)果上,我們是需要一個(gè)標(biāo)記,來(lái)找到數(shù)據(jù).
而我在上面講的橫向還是縱向的前提都是,對(duì)象,或者數(shù)組.
所以才會(huì)出現(xiàn)層級(jí).
但做標(biāo)記可以用字符串.
有很多種例子
最典型的就是 JSON,嚴(yán)格來(lái)講, JSON應(yīng)該是個(gè)字符串,但可以存儲(chǔ)多種數(shù)據(jù).
比如url
REST 模式根據(jù)層級(jí)也能傳一些東西,
非REST模式 可以用 key = value 方式存數(shù)據(jù), 而這些都是數(shù)據(jù).
在這篇文章里, 他沒(méi)有把 value 變成字符串,
但是把多維度的索引,合成了一個(gè)字符串. 進(jìn)行了降維.
這就很牛逼!
而且最后用上了 正則
腦子有點(diǎn)亂.
我們開(kāi)頭說(shuō), 本篇適用的情況是 ==
也就是 一一對(duì)應(yīng)的關(guān)系, 一個(gè)索引對(duì)應(yīng)一個(gè)值(這個(gè)值可能是數(shù)據(jù),可能是函數(shù))
之后說(shuō)的是多元條件, 相當(dāng)于是 多對(duì)一.
而字符串拼接降維和正則的使用,更多的是,
設(shè)置索引?
不只可以完成多對(duì)一,
也能完成一對(duì)多. 比如通過(guò)一個(gè)字符串, 可以獲取滿足正則條件的多個(gè)數(shù)據(jù)?
我肯定把一個(gè)簡(jiǎn)單的問(wèn)題,想復(fù)雜了.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>dddd</title>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
// 簡(jiǎn)化 if else
// 隱藏的 if else 全都是 if else
// 鍵值對(duì)
// 轉(zhuǎn)化成布爾值,
// 多元?
// 復(fù)雜多級(jí)運(yùn)算?
const result1 = (str) => {
if (str == "a") {
return "aa"
}else if (str == "b") {
return "bb"
}else if (str == "c") {
return "cc"
}else {
return "dd"
}
}
const result2 = (str) => {
switch (str){
case "a":
return "aa"
break;
case "b":
return "bb"
break;
case "c":
return "cc"
break;
default:
return "dd"
break;
}
}
const result3 = (str) => {
var obj = {
"a" : "aa",
"b" : "bb",
"c" : "cc",
"default" : "dd"
}
return obj[str] || obj["default"]
}
const actions = new Map([
["a","aa"],
["b","bb"],
["c","cc"],
["default","dd"]
])
const result4 = (str) => {
var end = actions.get(str) || actions.get("default");
return end
}
// var end = result4('a')
// console.log(end);
// 二元條件
const tResult1 = (master,str) => {
if (master == "mike") {
if (str == "a") {
return "aa"
}else if(...){
...
}
}else if (master == "peter") {
if (str == "a") {
return "aaa"
}else if(...){
...
}
}
}
const tResult2 = (master,str) => {
switch (master){
case "mike":
switch (str){
case "a":
return "aa"
...
}
case "peter":
switch (str){
case "a":
return "aa"
...
}
}
}
// 我原來(lái)的可能的思路是這樣的
const tResult3 = (master, str) => {
var obj = {
"peter" : {
"a" : "aaa",
"b" : "bbb",
"c" : "ccc",
"default" : "ddd"
},
"mike" : {
"a" : "aa",
"b" : "bb",
"c" : "cc",
"default" : "dd"
}
}
return obj[master][str] || obj[master]["default"]
}
// 又或者是這樣的
const tResult4 = (master, str) => {
var arr = [
{
master : "peter",
type : "a",
value : "aaa"
},
{
master : "peter",
type : "b",
value : "bbb"
},
{
master : "peter",
type : "c",
value : "ccc"
},
{
master : "peter",
type : "default",
value : "ddd"
},
{
master : "mike",
type : "a",
value : "aa"
},
{
master : "mike",
type : "b",
value : "bb"
},
{
master : "mike",
type : "c",
value : "cc"
},
{
master : "mike",
type : "default",
value : "dd"
}
]
var end1,end2;
arr.forEach((item, index) => {
if (item.master == master) {
if (item.type == str) {
end1 = item.value
}else if (item.type == "default"){
end2 = item.value
}
}
})
return end1 || end2
}
const tActions = new Map([
[{master : 'peter',type : "a"},"aaa"],
[{master : 'peter',type : "b"},"bbb"],
[{master : 'peter',type : "c"},"ccc"],
[{master : 'mike',type : "a"},"aa"],
[{master : 'mike',type : "b"},"aa"],
[{master : 'mike',type : "c"},"aa"]
])
// 本來(lái)我對(duì) new Map() 不熟悉
// 只知道有 get,set,has,delete
// 沒(méi)想到 可以 用[...actions] 的方式,瞬間變成真正的數(shù)組
// 然后就可以快樂(lè)的用數(shù)組的方法了.
// 不過(guò)話說(shuō)回來(lái), 這個(gè)方法,壓根用的不是 new Map() 完全可以用一個(gè)數(shù)組來(lái)進(jìn)行
// 他核心找到數(shù)據(jù)的方式,也是 filter 和 forEach..
const tResult5 = (master, type) => {
var action = [...tActions].filter(([item,value]) => {
return item.master == master && item.type == type
})
var end;
action.forEach(([item, value]) => {
end = value
})
return end
}
var end = tResult5("mike","b");
console.log(end);
//腦洞大開(kāi)的是 字符串拼接的方式,降維.
const sResult1 = (master, type) => {
if (`${master}_${type}` == "peter_a") {
return "aaa"
}
if (`${master}_${type}` == "peter_b") {
return "bbb"
}
if (`${master}_${type}` == "peter_c") {
return "ccc"
}
if (`${master}_${type}` == "mike_a") {
return "aa"
}
if (`${master}_${type}` == "mike_b") {
return "bb"
}
if (`${master}_${type}` == "mike_c") {
return "cc"
}
}
var end = sResult1("peter","b");
console.log(end);
const sResult2 = (master, type) => {
let str = `${master}_${type}`;
switch (str) {
case "peter_a" :
return "aaa";
case "peter_b" :
return "bbb";
case "peter_c" :
return "ccc";
case "mike_a" :
return "aa";
case "mike_b" :
return "bb";
case "mike_c" :
return "cc";
}
}
// var end = sResult2("mike","a");
// console.log(end);
const sResult3 = (master, type) => {
var str = `${master}_${type}`;
let obj = {
"peter_a" : "aaa",
"peter_b" : "bbb",
"peter_c" : "ccc",
"mike_a" : "aa",
"mike_b" : "bb",
"mike_c" : "cc",
"mike_default" : "dd",
"peter_default" : "ddd"
}
return obj[str] || obj[`${master}_default`]
}
const sResult4 = (master, type) => {
var str = `${master}_${type}`;
let obj = {
[/peter_[abc]/] : "aaa",// 雖然不會(huì)報(bào)錯(cuò), 但不可能得到想要的結(jié)果.該正則不起作用.
"mike_a" : "aa",
"mike_b" : "bb",
"mike_c" : "cc",
"mike_default" : "dd",
"peter_default" : "ddd"
}
return obj
return obj[str] || obj[`${master}_default`]
}
// var end = sResult4("peter","a");
// console.log(end);
const tActions3 = new Map([
[/^mike_[abc]$/,"aa"],
[/^peter_[abc]$/,"aaa"],
])
const sResult5 = (master, type) => {
var action = [...tActions3].filter(([item,value]) => {
return item.test(`${master}_${type}`)
})
var end;
action.forEach(([item,value]) => {
end = value;
})
return end
// 像上面這種,不是要執(zhí)行什么列表,而是返回值的情況可以
// var end;
// [...tActions3].forEach(([item, value]) => {
// if(item.test(`${master}_${type}`)) {
// end = value
//
// }
// })
// return end
}
var end = sResult5("peter","b");
console.log(end);
</script>
</body>
</html>