当前位置: 首页 > Web前端 > JavaScript

switch的四种写法你知道吗

时间:2023-03-27 15:51:30 JavaScript

JavaScriptswitch的四种写法你知道吗?不管你知不知道,反正我也不知道。我只知道一种用JavaScript编写switch语句的方法。但是涉及到分支的处理,有很多种写法。if分支的写法可以算作一种,switch分支的写法可以算作第二种,第三种就是使用策略模式。如果条件运算符也算上,嗯,正好四个。但是本文的主角是开关。大家都知道switch一般写成一个switch变量或者表达式,一个case常量。那么比如说,90分以上为优秀,80分以上为良好,90分以下为良好,60分以上为合格,60以下为不合格。使用switch大概会这样写:functioncalcGrade(score){constline=score/10|0;switch(line){case10:case9:return"excellent";案例8:返回“good”;案例七:案例六:返回“合格”;默认值:返回“不合格”;}}在代码中,score/10|0和Math.floor(score/10)的作用是一样的,就是除以10,取商的整数部分。这个开关用得相当好,它是一个巧妙的技巧,可以通过向上舍入来避免使用一长串if...else分支。但现在规则已经改变,将pass和goodcutoff从80减少到75,现在怎么办?上面的四舍五入方式还是可以的,不过这次除数不再是10,而是5。相应的,情况就多了很多:18、19、20优,15、16、17好,12、13、14个合格,其余不合格。写9个案例。真的是用if...else往上算比较好。是的?其实实用的switch还有更简单的写法:functioncalcGrade(score){switch(true){casescore>=90:return"excellent";案例分数>=75:返回“好”;casescore>=60:返回“合格”;默认值:返回“不合格”;}}是不是感觉有点奇怪?这根本就不是通常的switch表达式case常量,恰恰相反,switch常量case表达式!如果你拿着这个程序运行一下,你会发现一点问题都没有。因为-switch和case是按照===匹配的,所以不关心是表达式还是常量,或者说switch和case后面都可以跟表达式!对,表情!所以在上面的例子中,将switch(true)更改为switch(2>1)具有相同的效果。嗯,脑洞已经打开了。switch有多少种写法并不重要。接下来要研究的是switch的变体——看到C#有switch表达式,羡慕不已,能实现吗?别贪心,JavaScript中的一切都可以是一个表达式……如果不行,就用IIFE函数封装一个calcGrade(score){return(value=>{switch(true){casevalue>=90:return"excellent";casevalue>=75:return"good";casevalue>=60:return"qualified";default:return"unqualified";}})(score);}注意这里使用score作为IIFE的参数因为在实际使用中,可能需要传入一个表达式,这种情况下,应该提前求值,而且只求一次(避免代入带来的副作用)。但是,这样的封装显然是没有意义的。如果真的要这样封装,最好封装成一个策略:functioncalcGrade(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:"qualified"},{t:()=>true,v:"failed"},]);}每个策略都是一个包含测试器(t)和值(v)的对象。tester是一个判断函数,传入需要判断的值,即switch(expression)中的表达式,预判后这个表达式也作为IIFE的参数传入。应用策略的过程简单粗暴,就是找到第一个满足条件的策略,取出它的值。当然,这样的策略有点大材小用。当真正需要一个策略的时候,这个策略通常不是一个值,而是一个行为,也就是一个函数。我们知道在switch语句中,每个case都在同一个作用域内,所以不能在两个case语句中声明同一个局部变量。虽然用{}换行可以解决这些问题,但是代码看起来不太好看,尤其要注意不要忘记换行。如果使用策略,可能看起来顺眼一些,也不用担心break的问题:这里演示一下,在策略行为中,先输出分数,再输出等级回。functioncalcGrade(score){return((value,rules)=>rules.find(({t})=>t(value)).fn(value))(score,[{t:n=>n>=90,fn:score=>{constgrade="优秀";console.log(grade,score);returngrade;}},{t:n=>n>=75,fn:score=>{constgrade="良好";console.log(grade,score);returngrade;}},{t:n=>n>=60,fn:score=>{constgrade="合格";console.log(grade,score);返回成绩;}},{t:()=>true,fn:score=>{constgrade="不合格";console.log(等级,分数);返回成绩;}},]);}代码确实有点长,因为里面有策略行为逻辑。如果真的要作为switch表达式使用的话,policy部分应该是一个表达式,不要太长。上面代码中,policy的行为类似,可以封装成一个函数,这样就可以写成表达式的形式:functioncalcGrade(score){constprintGrade=(grade,score)=>{console.日志(成绩,分数);返回成绩;};return((value,rules)=>rules.find(({t})=>t(value)).fn(value))(score,[{t:n=>n>=90,fn:score=>printGrade("优秀",分数)},{t:n=>n>=75,fn:分数=>printGrade("好",分数)},{t:n=>n>=60,fn:score=>printGrade("Qualified",score)},{t:()=>true,fn:score=>printGrade("Unqualified",score)},]);}现在看看它看起来像吗?上面的代码形式不同,做的事情几乎是一样的,没有比较哪个好哪个差。顺眼的就是高雅,不顺眼的就是不被宠爱。在不同的情况下,选择合适的方法是好的。上面的代码使用find()来查找策略。如果改用filter(),又是另一番景象~(~ ̄▽ ̄)~。