JavaScript 的 switch 有四樣寫法,你都知道哪些?
JavaScript 的 switch 語句只有一種寫法。其他的寫法,if 分支寫法可以算一種,switch 分支寫法可以算第二種,第三種是使用策略模式,如果要把條件運算符也算上的話,嗯,剛好四種。
switch一般寫法
switch 的寫法一般來說是 switch 變量或表達式,case 常量,比如:一個百分制成績,90 及 90 分以上算優秀,80 及以上 90 以下算良好,60 及以上 80 以下算合格,60 以下為不合格,用 switch 表示這樣寫:
function calcGrade(score) { const line = score / 10 | 0; switch (line) { case 10: case 9: return "優秀"; case 8: return "良好"; case 7: case 6: return "合格"; default: return "不合格"; } }
代碼中score / 10 | 0和Math.floor(score / 10)是一樣的效果,就是除以 10 取商的整數部分。
這段 switch 用得中規中矩,用取整的辦法來避免使用一長串 if ... else 分支也算是取了巧。
但現在將合格和良好的分隔點從 80 分降到 75 分,要怎么寫?
其實改動不用太大,不過這次除數不再是 10,而是 5。相應地,case 也多了很多:
18、19、20 是優秀
15、16、17 是良好
12、13、14 是合格
剩下的是不合格
寫 9 個 case,真不如用 if ... else 算了。
switch簡單寫法
是嗎?其實用 switch 也有簡單一些的寫法:
function calcGrade(score) { switch (true) { case score >= 90: return "優秀"; case score >= 75: return "良好"; case score >= 60: return "合格"; default: return "不合格"; } }
這其實是switch 常量 case 表達式!這段跑程序沒問題,是因為——switch 和 case 是按 === 來匹配的,它并不在乎是表達式還是常量,或者說,switch 和 case 后面都可以接表達式!
是的,表達式!
所以上面那個示例中,把switch(true)改成switch( 2 > 1)也是一樣的效果。
好啦,腦洞已開。switch 到底有多少種寫法已經不重要了。接下來要研究的是 switch 的變種 。
IIFE 封裝
看到 C# 有 switch 表達式,眼饞,能實現嗎?
不用眼饞,JavaScript 里一切都可以是表達式 …… 如果不是,用 IIFE 封裝一個就是了
function calcGrade(score) { return (value => { switch (true) { case value >= 90: return "優秀"; case value >= 75: return "良好"; case value >= 60: return "合格"; default: return "不合格"; } })(score); }
注意這里把score作為 IIFE 的參數,是因為在實際使用中,可能需要傳入的是一個表達式。這種情況下應該提前求值,而且只求一次(避免替在的副作用)。
封成策略
不過這樣的封裝顯然沒什么意義,如果真要這樣封裝,不如封成策略:
function calcGrade(score) { return ((value, rules) => rules.find(({ t }) => t(value)).v)( score, [ { t: n => n >= 90, v: "優秀" }, { t: n => n >= 75, v: "良好" }, { t: n => n >= 60, v: "合格" }, { t: () => true, v: "不合格" }, ] ); }
每項策略都是一個含有 tester (t) 和值 (v) 的對象。tester 是一個判斷函數,傳入需要判斷的值,也就是switch (表達式)這里表達式,而這個表達式也是提前求值之后作為 IIFE 的參數傳入的。應用策略的過程簡單粗暴,就是找到第一個符合條件的策略,把它的值取出來。
當然這樣用策略有點大材小用。真正需要用策略的情況,策略中通常不是一個值,而是一個行為,也就函數。
我們知道在 switch 語句中,各個 case 之間是在同一個作用域內,所以不能在兩個 case 語句中聲明同一個局部變量。雖然用{ }包裹可以解決這些問題,但代碼看起來不怎么好看,特別是還要注意不要忘了break。如果用策略的話,看起來可能會順眼一眼,也不用擔心 break 的問題:
這里為了演示,在策略行為中將先輸出成績,再返回等級。
function calcGrade(score) { return ((value, rules) => rules.find(({ t }) => t(value)).fn(value))( score, [ { t: n => n >= 90, fn: score => { const grade = "優秀"; 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; } }, ] ); }
代碼長是融入邏輯,如果真的是要當作 switch表達式來用的話,策略部分應該是一個表達式就不會太長。上面的代碼中,策略行為相似,可以封裝成一個函數,這樣就能寫成表達式的形式了:
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("優秀", score) }, { t: n => n >= 75, fn: score => printGrade("良好", score) }, { t: n => n >= 60, fn: score => printGrade("合格", score) }, { t: () => true, fn: score => printGrade("不合格", score) }, ] ); }
現在看起來是不是像樣了?
其實很多時候書寫表達只要代碼合適就可以。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/127675.html
摘要:對于來說,表示元素,除了優先級更高之外,與選擇器相同。再做實驗,前后分別設置兩個空格時,獲取到的值只有一個空格。結論設置值內聯樣式選擇器選擇器也都是會把多余空格變成一個空格。 今天突然發現一個有趣的現象document.querySelector(:root) === document.documentElement showImg(https://segmentfault.com/i...
摘要:對于來說,表示元素,除了優先級更高之外,與選擇器相同。再做實驗,前后分別設置兩個空格時,獲取到的值只有一個空格。結論設置值內聯樣式選擇器選擇器也都是會把多余空格變成一個空格。 今天突然發現一個有趣的現象document.querySelector(:root) === document.documentElement showImg(https://segmentfault.com/i...
摘要:是阿里團隊開發的前端適配方案,也是用的的方法。那么第一種方法其實已經能解決前端適配問題了,為什么阿里還要開發一個呢在第一種方法中,時沒有任何問題,但是在或者更高的手機屏幕上,因為物理像素的增加,存在小于的顯示空間。 話說我剛工作的時候,就開始用rem了,過了沒多久,接觸到了flexible,系統化且支持iOS的retina屏迅速征服了我,最近又看到了大漠大神的vw。所以本文想完成一篇一...
摘要:是阿里團隊開發的前端適配方案,也是用的的方法。那么第一種方法其實已經能解決前端適配問題了,為什么阿里還要開發一個呢在第一種方法中,時沒有任何問題,但是在或者更高的手機屏幕上,因為物理像素的增加,存在小于的顯示空間。 話說我剛工作的時候,就開始用rem了,過了沒多久,接觸到了flexible,系統化且支持iOS的retina屏迅速征服了我,最近又看到了大漠大神的vw。所以本文想完成一篇一...
摘要:是阿里團隊開發的前端適配方案,也是用的的方法。那么第一種方法其實已經能解決前端適配問題了,為什么阿里還要開發一個呢在第一種方法中,時沒有任何問題,但是在或者更高的手機屏幕上,因為物理像素的增加,存在小于的顯示空間。 話說我剛工作的時候,就開始用rem了,過了沒多久,接觸到了flexible,系統化且支持iOS的retina屏迅速征服了我,最近又看到了大漠大神的vw。所以本文想完成一篇一...
閱讀 547·2023-03-27 18:33
閱讀 732·2023-03-26 17:27
閱讀 630·2023-03-26 17:14
閱讀 591·2023-03-17 21:13
閱讀 520·2023-03-17 08:28
閱讀 1801·2023-02-27 22:32
閱讀 1292·2023-02-27 22:27
閱讀 2177·2023-01-20 08:28