JS中switch的四種寫法示例
引言
JavaScript 的 switch 有四樣寫法,你知道么?不管你知道不知道,反正我是不知道。
我所知道的 JavaScript 的 switch 語句只有一種寫法。但要說到對(duì)分支的處理,寫法可就多了去了。if 分支寫法可以算一種,switch 分支寫法可以算第二種,第三種是使用策略模式,如果要把條件運(yùn)算符也算上的話,嗯,剛好四種。
switch一般寫法
不過本文的主角是 switch。大家都了解 switch 的寫法一般來說是 switch 變量或表達(dá)式,case 常量。嗯,比如說,一個(gè)百分制成績(jī),90 及 90 分以上算優(yōu)秀,80 及以上 90 以下算良好,60 及以上 80 以下算合格,60 以下為不合格,用 switch 大概會(huì)這么寫:
function calcGrade(score) { const line = score / 10 | 0; switch (line) { case 10: case 9: return "優(yōu)秀"; case 8: return "良好"; case 7: case 6: return "合格"; default: return "不合格"; } }
代碼中 score / 10 | 0
和 Math.floor(score / 10)
是一樣的效果,就是除以 10 取商的整數(shù)部分。
這段 switch 用得中規(guī)中矩,用取整的辦法來避免使用一長(zhǎng)串 if ... else 分支也算是取了巧。
但是現(xiàn)在規(guī)則改了,將合格和良好的分隔點(diǎn)從 80 分降到 75 分,該怎么辦?
按上面取整的辦法依然可以,不過這次除數(shù)不再是 10,而是 5。相應(yīng)地,case 也多了很多:
- 18、19、20 是優(yōu)秀
- 15、16、17 是良好
- 12、13、14 是合格
- 剩下的是不合格
寫 9 個(gè) case,真不如用 if ... else 算了。
switch簡(jiǎn)單寫法
是嗎?其實(shí)用 switch 也有簡(jiǎn)單一些的寫法:
function calcGrade(score) { switch (true) { case score >= 90: return "優(yōu)秀"; case score >= 75: return "良好"; case score >= 60: return "合格"; default: return "不合格"; } }
是不是感覺有些奇怪?這完全不是習(xí)慣了的 switch 表達(dá)式 case 常量,而是正好相反,switch 常量 case 表達(dá)式!如果你拿這段程序去跑一下,會(huì)發(fā)現(xiàn)一點(diǎn)問題都沒有。因?yàn)?mdash;—switch 和 case 是按 ===
來匹配的,它并不在乎是表達(dá)式還是常量,或者說,switch 和 case 后面都可以接表達(dá)式!
是的,表達(dá)式!
所以上面那個(gè)示例中,把 switch(true)
改成 switch( 2 > 1)
也是一樣的效果。
好啦,腦洞已開。switch 到底有多少種寫法已經(jīng)不重要了。接下來要研究的是 switch 的變種 。
IIFE 封裝
看到 C# 有 switch 表達(dá)式,眼饞,能實(shí)現(xiàn)嗎?
不用眼饞,JavaScript 里一切都可以是表達(dá)式 …… 如果不是,用 IIFE 封裝一個(gè)就是了
function calcGrade(score) { return (value => { switch (true) { case value >= 90: return "優(yōu)秀"; case value >= 75: return "良好"; case value >= 60: return "合格"; default: return "不合格"; } })(score); }
注意這里把 score
作為 IIFE 的參數(shù),是因?yàn)樵趯?shí)際使用中,可能需要傳入的是一個(gè)表達(dá)式。這種情況下應(yīng)該提前求值,而且只求一次(避免替在的副作用)。
封成策略
不過這樣的封裝顯然沒什么意義,如果真要這樣封裝,不如封成策略:
function calcGrade(score) { return ((value, rules) => rules.find(({ t }) => t(value)).v)( score, [ { t: n => n >= 90, v: "優(yōu)秀" }, { t: n => n >= 75, v: "良好" }, { t: n => n >= 60, v: "合格" }, { t: () => true, v: "不合格" }, ] ); }
每項(xiàng)策略都是一個(gè)含有 tester (t
) 和值 (v
) 的對(duì)象。tester 是一個(gè)判斷函數(shù),傳入需要判斷的值,也就是 switch (表達(dá)式)
這里表達(dá)式,而這個(gè)表達(dá)式也是提前求值之后作為 IIFE 的參數(shù)傳入的。應(yīng)用策略的過程簡(jiǎn)單粗暴,就是找到第一個(gè)符合條件的策略,把它的值取出來。
當(dāng)然這樣用策略有點(diǎn)大材小用。真正需要用策略的情況,策略中通常不是一個(gè)值,而是一個(gè)行為,也就函數(shù)。
我們知道在 switch 語句中,各個(gè) case 之間是在同一個(gè)作用域內(nèi),所以不能在兩個(gè) case 語句中聲明同一個(gè)局部變量。雖然用 { }
包裹可以解決這些問題,但代碼看起來不怎么好看,特別是還要注意不要忘了 break
。如果用策略的話,看起來可能會(huì)順眼一眼,也不用擔(dān)心 break 的問題:
這里為了演示,在策略行為中將先輸出成績(jī),再返回等級(jí)。
function calcGrade(score) { return ((value, rules) => rules.find(({ t }) => t(value)).fn(value))( score, [ { t: n => n >= 90, fn: score => { const grade = "優(yōu)秀"; console.log(grade, score); return grade; } }, { t: n => n >= 75, fn: score => { const grade = "良好"; console.log(grade, score); return grade; } }, { t: n => n >= 60, fn: score => { const grade = "合格"; console.log(grade, score); return grade; } }, { t: () => true, fn: score => { const grade = "不合格"; console.log(grade, score); return grade; } }, ] ); }
代碼確實(shí)有點(diǎn)長(zhǎng),因?yàn)橛胁呗孕袨檫壿嬙诶锩?。如果真的是要?dāng)作 switch 表達(dá)式來用的話,策略部分應(yīng)該是一個(gè)表達(dá)式,不會(huì)太長(zhǎng)的。上面的代碼中,策略行為相似,可以封裝成一個(gè)函數(shù),這樣就能寫成表達(dá)式的形式了:
function calcGrade(score) { const printGrade = (grade, score) => { console.log(grade, score); return grade; }; return ((value, rules) => rules.find(({ t }) => t(value)).fn(value))( score, [ { t: n => n >= 90, fn: score => printGrade("優(yōu)秀", score) }, { t: n => n >= 75, fn: score => printGrade("良好", score) }, { t: n => n >= 60, fn: score => printGrade("合格", score) }, { t: () => true, fn: score => printGrade("不合格", score) }, ] ); }
現(xiàn)在看起來是不是像樣了?
上面的代碼形式各異,干的事情都差不多,也沒有誰優(yōu)誰劣的比較??吹庙樠墼趺炊純?yōu)雅,看不順眼怎么都不受寵。在不同的情況下,選用合適的做法就好。上面的代碼使用的 find()
來查找策略,如果改用 filter()
,那又會(huì)是另一番景象了。
以上就是JS中switch的四種寫法示例的詳細(xì)內(nèi)容,更多關(guān)于JS switch寫法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript基礎(chǔ)之?dāng)?shù)據(jù)類型詳解
這篇文章主要介紹了如何理解JavaScript中的數(shù)據(jù)類型,幫助大家更好的學(xué)習(xí)JavaScript,感興趣的朋友可以了解下2021-11-11Javascript學(xué)習(xí)筆記之函數(shù)篇(六) : 作用域與命名空間
本文主要講述了javascript中作用域和命名空間的區(qū)別,十分的詳細(xì),這里推薦給大家,希望小伙伴能有所收獲2014-11-11使用js聲明數(shù)組,對(duì)象在jsp頁面中(獲得ajax得到j(luò)son數(shù)據(jù))
使用js聲明數(shù)組,對(duì)象在jsp頁面中(獲得ajax得到j(luò)son數(shù)據(jù))。需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-11-11JavaScript 創(chuàng)建運(yùn)動(dòng)框架的實(shí)現(xiàn)代碼
本篇文章是對(duì),在JavaScript中創(chuàng)建運(yùn)動(dòng)框架的實(shí)現(xiàn)方法進(jìn)行了介紹。需要的朋友參考下2013-05-05Javascript入門學(xué)習(xí)第九篇 Javascript DOM 總結(jié)
作為一個(gè)js-DOM開發(fā)者,你必須知道的一些DOM方法:2008-07-07