当前位置: 首页 > 科技观察

编写好的JS条件语句的5条规则

时间:2023-03-20 16:44:16 科技观察

在使用JavaScript工作时,我们经常会处理条件语句,这里有5个技巧可以帮助您编写更好/更干净的条件语句。内容:使用Array.includes进行多重判断减少嵌套,提前返回使用默认参数和解构倾向于遍历对象而不是Switch语句使用Array.every&Array.some进行全部/部分判断总结1.使用Array.includes进行多重判断我们看下面这个例子://conditionfunctiontest(fruit){if(fruit=='apple'||fruit=='strawberry'){console.log('red');}}初看,上面的例子看起来美好的。如果我们有更多名为樱桃和蔓越莓的红色水果会怎么样?我们要用更多||扩展条件语句吗?我们可以用Array.includes(Array.includes)重写条件语句。functiontest(fruit){constredFruits=['apple','strawberry','cherry','cranberries'];if(redFruits.includes(fruit)){console.log('red');}}我们把红色的水果(红色水果)的判断条件提取到数组中。这样代码看起来更干净。2.少嵌套,早点返回让我们扩展前面的例子,让它包含两个条件。如果没有传入参数fruit,则抛错接受quantity参数,当数量大于10时打印出来functiontest(fruit,quantity){constredFruits=['apple','strawberry','cherry','cranberries'];//条件一:水果必须有值if(fruit){//条件二:必须是红色if(redFruits.includes(fruit)){console.log('red');//条件3:数量大于10if(quantity>10){console.log('bigquantity');}}}else{thrownewError('Nofruit!');}}//测试结果test(null);//错误:Nofruitstest('apple');//print:redtest('apple',20);//print:red,bigquantity在上面的代码中,我们有:1个if/else语句,过滤掉无效语句3层ifnestedstatements(condition1,2&3)我个人遵循的规则是发现无效条件时尽快返回。/_当发现无效语句时,返回_/functiontest(fruit,quantity){constredFruits=['apple','strawberry','cherry','cranberries'];//条件1:如果如果尽快抛出错误(!fruit)thrownewError('Nofruit!');//条件二:必须是红色if(redFruits.includes(fruit)){console.log('red');//条件三:??必须是大质量if(quantity>10){console.log('bigquantity');}}}这样就少了一个嵌套语句。这种编码风格很棒,??尤其是当你有很长的if语句时(想象你需要滚动到底部才能发现有一个else语句,这并不酷)我们可以通过反转条件并提前返回来进一步减少它嵌套如果。看下面我们是如何处理判断条件2的:;//条件一:尽早抛出错误if(!fruit)thrownewError('Nofruit!');//条件二:当水果不是红色时停止执行if(!redFruits.includes(fruit))return;console.log('red');//条件3:必须是高质量的if(quantity>10){console.log('bigquantity');}}通过反转条件2,我们的代码避免了嵌套语句。当我们需要进行很长的逻辑判断时,特别是当我们希望在条件不满足时能够停下来处理时,这个技巧就非常有用。这样做并不难。问问自己,这个版本(没有嵌套)是否比之前的版本(两层嵌套条件)更好、更易读?但对我来说,我会保留以前的版本(有两层嵌套)。这是因为:代码更短更直接,if嵌套更清晰。倒置判断条件可能会增加思考的负担(增加认知负荷)。因此,尽量减少嵌套,尽快返回,但不要过度。如果您感兴趣,请查看有关该主题的文章和StackOverflow讨论。AvoidElse,ReturnEarly作者:TimOxleyStackOverflow关于if/else编码风格的讨论3。使用默认参数和解构我想下面的代码你可能很熟悉,在JavaScript中我们总是需要检查null/undefined值并分配默认值:functiontest(fruit,quantity){if(!fruit)return;//如果不传入quantity参数,则设置默认值为1constq=quantity||1;console.log(`Wehave${q}${fruit}!`);}//testresultstest('banana');//Wehave1banana!test('apple',2);//Wehave2apple!我们实际上可以通过声明一个默认的函数参数来消除变量q。functiontest(fruit,quantity=1){//如果不传入quantity参数,则设置默认值为1if(!fruit)return;console.log(`Wehave${quantity}${fruit}!`);}//testresultstest('banana');//Wehave1banana!test('apple',2);//Wehave2apple!这更直观,不是吗?请注意,每个声明都有其自己的默认参数。例如,我们也可以给水果赋默认值:functiontest(fruit='unknown',quantity=1)。如果水果是一个对象呢?我们可以分配一个默认参数吗?functiontest(fruit){//存在值时打印fruit的值if(fruit&&fruit.name){console.log(fruit.name);}else{console.log('unknown');}}//testresultstest(undefined);//unknowntest({});//unknowntest({name:'apple',color:'red'});//applelook在上面的例子中,我们要打印可能存在的name属性水果对象。否则我们打印未知。我们可以使用默认参数和解构来避免判断条件fruit&&fruit.name//解构-只获取name属性//给一个空对象赋默认值functiontest({name}={}){console.log(name||'unknown');}//testresultstest(undefined);//unknowntest({});//unknowntest({name:'apple',color:'red'});//apple因为我们只需要name属性,我们可以使用{name}来解构参数,然后我们可以使用变量name而不是fruit.name。我们还需要将空对象{}声明为默认值。如果我们不这样做,在执行test(undefined)时会出现无法解构undefined或null的错误。因为undefined里面没有name属性。如果你不介意使用第三方库,有一些方法可以减少空值检查:使用Lodashget函数使用Facebook的开源idx库(使用Babeljs)下面是一个使用Lodash的例子:functiontest(fruit){//获取属性名,如果没有属性名,默认值为unknownconsole.log(__.get(fruit,'name','unknown');}//testresultstest(undefined);//unknowntest({});//unknowntest({name:'apple',color:'red'});//apple,你可以在jsbin中运行demo代码。另外,如果你是函数式编程的爱好者,你可以选择使用Lodashfp,LodashFormula版本的函数(方法改为get或getOr)。4.更喜欢对象遍历而不是Switch语句我们看下面的例子,我们想根据颜色打印出水果:functiontest(color){//使用条件语句找到对应颜色的水果switch(color){case'red':return['apple','strawberry'];case'yellow':return['banana','pineapple'];案例'紫色':return['grape','plum'];default:return[];}}//testresultstest(null);//[]test('yellow');//['banana','pineapple']上面的代码看起来是正确的,但是我发现了一些冗余。使用对象遍历实现同样的结果,语法看起来更简洁:constfruitColor={red:['apple','strawberry'],yellow:['banana','pineapple'],purple:['grape','plum']};functiontest(color){returnfruitColor[color]||[];}或者您可以使用Map实现相同的结果:constfruitColor=newMap().set('red',['apple','strawberry']).set('yellow',['banana','pineapple']).set('purple',['grape','plum']);functiontest(color){returnfruitColor.get(color)||[];}Map是ES2015规范之后实现的一种对象类型,可以存储key和value值。但是我们应该禁止使用switch语句吗?答案是不要限制自己。就个人而言,我尽可能使用对象遍历,但我并不严格遵守它,而是使用对当前场景更有意义的任何东西。ToddMotto有一篇关于switch语句与对象遍历的更深入的文章,你可以在这里阅读TL;DR;重构语法在上面的示例中,我们能够重构我们的代码以使用Array.filter来实现相同的效果。constfruits=[{name:'apple',color:'red'},{name:'strawberry',color:'red'},{name:'banana',color:'yellow'},{name:'菠萝',color:'yellow'},{name:'grape',color:'purple'},{name:'plum',color:'purple'}];functiontest(color){returnfruits.filter(f=>f.color==color);}实现相同结果的方法不止一种,我们在上面展示了4种。5.使用Array.every&Array.some进行all/some判断最后这个建议更多的是利用JavaScriptArray的内置方法来减少代码行数。看下面的代码,我们要检查是否所有的水果都是红色的:constfruits=[{name:'apple',color:'red'},{name:'banana',color:'yellow'},{name:'grape',color:'purple'}];functiontest(){letisAllRed=true;//条件:所有水果都是红色for(letffruits){if(!isAllRed)break;isAllRed=(f.color=='red');}console.log(isAllRed);//false}代码好长!我们可以通过Array.every减少代码行数:constfruits=[{name:'apple',color:'red'},{name:'banana',color:'yellow'},{name:'grape',color:'purple'}];functiontest(){constisAllRed=fruits.every(f=>f.color=='red');console.log(isAllRed);//false}现在更简洁了,不是吗?同理,如果我们要测试是否有红色水果,我们可以使用Array.some一行代码实现。constfruits=[{name:'apple',color:'red'},{name:'banana',color:'yellow'},{name:'grape',color:'purple'}];functiontest(){//条件:任意水果是红色的constisAnyRed=fruits.some(f=>f.color=='red');console.log(isAnyRed);//true}6.总结让我们一起编写更具可读性的高性能代码。我希望你能从这篇文章中学到一些东西。这里的所有都是它的。编码愉快!