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

编写更好的JavaScript条件语句和匹配条件的技巧

时间:2023-03-20 17:43:05 科技观察

介绍如果您像我一样喜欢干净的代码,那么您希望尽量减少代码中条件语句的数量。通常,面向对象编程允许我们避免条件语句并用继承和多态性代替它们。我认为我们应该尽可能地遵循这些原则。正如我在另一篇文章BestPracticesforJavaScriptCleanCode中提到的,你写的代码不仅是给机器看的,也是给“未来的自己”和“其他人”的。另一方面,由于各种原因,我们的代码可能以条件结束。也许修复bug的时间很紧,也许不使用条件语句会对我们的代码库进行重大更改,等等。本文将解决这些问题并帮助您组织您使用的条件语句。提示以下是关于如何构建if...else语句以及如何用更少的代码做更多事情的提示。阅读愉快!1.重要的事情***。小细节,但重要的是不要使用否定条件(这可能会造成混淆)。此外,对布尔值使用条件速记。这个不用强调,尤其是否定条件句,不符合正常的思维方式。坏:constisEmailNotVerified=(email)=>{//implementation}if(!isEmailNotVerified(email)){//做某事...}if(isVerified===true){//做某事...}好的:constisEmailVerified=(email)=>{//implement}if(isEmailVerified(email)){//dosomething...}if(isVerified){//dosomething...}现在,整理完上面的东西后,我们可以开始了。2、多个条件,使用Array.includes假设我们要在函数中查询汽车型号是雷诺还是标致。那么代码可能看起来像这样:renault');//output'modelvalid'考虑到我们只有两个模型,这似乎可以接受,但是如果我们还想检查另一个或几个模型怎么办?如果我们添加更多的or语句,那么代码将变得不可维护且不那么干净。为了更简洁,我们可以这样重写函数:constcheckCarModel=(model)=>{if(['peugeot','renault'].includes(model)){console.log('modelvalid');}}checkCarModel('renault');//输出'modelvalid'上面的代码已经很漂亮了。为了进一步改进它,我们可以创建一个变量来保存汽车模型:constcheckCarModel=(model)=>{constmodels=['peugeot','renault'];if(models.includes(model)){console.log('modelvalid');}}checkCarModel('雷诺');//output'modelvalid'现在,如果我们想检查更多模型,只需添加一个新的数组元素。此外,如果重要的话,我们还可以在函数范围之外定义模型变量,并在需要的地方重用它。这种方法使我们能够集中管理并使维护变得轻而易举,因为我们只需要更改代码中的一个地方。3.匹配所有条件,使用Array.every或Array.find在这种情况下,我们要检查每个车型是否是传入函数的车型。为了以更命令的方式做到这一点,我们会这样做:constcars=[{model:'renault',year:1956},{model:'peugeot',year:1968},{model:'ford',year:1977}];constcheckEveryModel=(model)=>{letisValid=true;for(letcarofcars){if(!isValid){break;}isValid=car.model===model;}returnisValid;}console.log(checkEveryModel('renault'));//outputfalse如果你更喜欢命令式的风格,上面的代码可能没问题。另一方面,如果您不关心幕后发生的事情,那么您可以重写上面的函数并使用Array.every或Array.find来获得相同的结果。constcheckEveryModel=(model)=>{returncars.every(car=>car.model===model);}console.log(checkEveryModel('renault'));//使用Array.find输出false并做小调整,我们可以得到相同的结果。行为是相同的,因为两个函数都对数组中的每个元素执行回调,并在发现虚假项目时立即返回false。constcheckEveryModel=(model)=>{returncars.find(car=>car.model!==model)===undefined;}console.log(checkEveryModel('雷诺'));//输出false4.匹配一些条件,使用Array.someArray.every来匹配所有条件,这个方法可以很方便地检查我们的数组是否包含某个元素或某些元素。为此,我们需要提供一个回调并根据条件返回一个布尔值。我们可以通过编写与我们之前编写的类似的for...loop语句来获得相同的结果。但幸运的是,有很酷的JavaScript函数可以帮助我们做到这一点。constcars=[{model:'renault',year:1956},{model:'peugeot',year:1968},{model:'ford',year:1977}];constcheckForAnyModel=(model)=>{returncars.some(car=>car.model===model);}console.log(checkForAnyModel('renault'));//输出true5.早点返回而不是用if...elsebranch学生时代,有人教我:一个函数应该只有一个return语句,而且只能从一个地方返回。如果处理得当,这个方法还不错。我的意思是我们应该意识到在某些情况下它会导致条件嵌套地狱。如果任其发展,多个分支和if...else嵌套可能会很痛苦。另一方面,如果代码库很大并且包含很多行代码,深层次的return语句可能会导致问题。这些天我们都在实践关注点分离和SOLID原则,所以很少有太多的代码行。让我用一个例子来解释这个问题。假设我们要显示给定车辆的型号和生产年份:constcheckModel=(car)=>{letresult;//首先定义一个结果变量//检查是否有汽车if(car){//检查是否有汽车型号if(car.model){//检查是否有汽车年份if(car.year){result=`Carmodel:${car.model};Manufacturingyear:${car.year};`;}else{result='Nocaryear';}}else{result='Nocarmodel'}}else{result='Nocar';}returnresult;//我们单独的返回语句}console.log(checkModel());//Output'Nocar''console.log(checkModel({year:1988}));//输出'Nocarmodel'console.log(checkModel({model:'ford'}));//输出'Nocaryear'console.log(checkModel({model:'ford',year:1988}));//输出'Carmodel:ford;Manufacturingyear:1988;'正如您所看到的,尽管这个例子中的问题很简单,但上面的代码太长了。想象一下,如果我们有更复杂的逻辑会发生什么。很多if...else语句。我们可以重构上面的函数,分解成步骤,稍微改进一下。例如,使用三元运算符,包括&&条件等。但是,在这里我直接跳到***并向您展示借助现代JavaScript功能和多个return语句可以使您的代码变得多么干净。constcheckModel=({model,year}={})=>{if(!model&&!year)return'Nocar';if(!model)return'Nocarmodel';if(!year)return'Nocaryear';//这里可以任意操作模型或年份//确保它们存在//不再检查//doSomething(model);//doSomethingElse(年);return`Carmodel:${model};Manufacturingyear:${year};`;}console.log(checkModel());//输出'Nocar'console.log(checkModel({year:1988}));//output'Nocarmodel'console.log(checkModel({model:'ford'}));//输出'Nocaryear'console.log(checkModel({model:'ford',year:1988}));//输出'Carmodel:ford;Manufacturingyear:1988;'在重构版本中,我们包括解构和默认参数。默认参数确保我们在传入undefined时有可用于解构的值。注意,如果传入null,函数会报错。这也是前一种方法的优点,因为当传入null时,该方法会输出'Nocar'。对象解构确保函数只取需要的东西。例如,如果我们在给定的车辆对象中包含一个额外的属性,则该属性将无法在我们的函数中访问。根据偏好,开发人员将选择其中一种方法。实际上,编写的代码通常介于两者之间。许多人发现if...else语句更容易理解并帮助他们更轻松地遵循程序流程。6.使用索引或映射而不是switch语句假设我们想要根据给定的国家/地区获取汽车模型。constgetCarsByState=(state)=>{switch(state){case'usa':return['Ford','Dodge'];case'france':return['Renault','Peugeot'];case'italy':return['Fiat'];default:return[];}}console.log(getCarsByState());//output[]console.log(getCarsByState('usa'));//output['Ford','Dodge']console.log(getCarsByState('italy'));//Output['Fiat']申诉代码可以重构,完全去掉switch语句。constcars=newMap().set('usa',['Ford','Dodge']).set('france',['Renault','Peugeot']).set('意大利',['菲亚特']);constgetCarsByState=(state)=>{returncars.get(state)||[];}console.log(getCarsByState());//输出[]console.log(getCarsByState('usa'));///output['Ford','Dodge']console.log(getCarsByState('italy'));//output['Fiat']或者,我们也可以为每个国家/地区创建一个包含可用汽车列表和需要时使用。不过这是题外话,本文的主题是关于条件句的。更合适的修改是使用对象文字。constcarState={美国:['福特','道奇'],法国:['雷诺','标致'],意大利:['菲亚特']};constgetCarsByState=(state)=>{returncarState[state]||[];}console.log(getCarsByState());//output[]console.log(getCarsByState('usa'));//output['Ford','Dodge']console.log(getCarsByState('france)'));//Output['Renault','Peugeot']7.使用自判断链接和空合并到这一段,我终于可以说“***”了。在我看来,这两个特性对于JavaScript语言非常有用。作为来自C#世界的人,我可以说我经常使用它们。在撰写本文时,这些还没有得到完全支持。所以这样写的代码,需要用Babel来编译。你可以在这里的自我判断链接和这里的空合并查看。自判断链接允许我们处理树结构而无需显式检查是否存在中间节点。nullmerge可以保证在节点不存在的时候会有一个默认值。使用自判断链接会有很好的效果。让我们用一些例子来支持上述结论。一开始我们还是用老方法:constcar={model:'Fiesta',manufacturer:{name:'Ford',address:{street:'SomeStreetName',number:'5555',state:'USA'}}}//获取车型constmodel=car&&car.model||'defaultmodel';//获取厂家地址conststreet=car&&car.manufacturer&&car.manufacturer.address&&car.manufacturer.address.street||'defaultstreet';//请求一个不存在的属性constphoneNumber=car&&car.manufacturer&&car.manufacturer.address&&car.manufacturer.phoneNumber;console.log(model)//output'Fiesta'console.log(street)//output'SomeStreetName'console.log(phoneNumber)//outputundefined因此,如果我们想知道制造商是否来自美国并打印结果,代码将是这样的:=='USA'){console.log('IsfromUSA');}}checkCarManufacturerState()//Output'IsfromUSA'我不需要重复如果obj代码会有多混乱等结构比较复杂。许多库,例如lodash,都有自己的函数作为替代。但这不是我们想要的,我们想要的是在原生js中做同样的事情。我们来看看新方法://获取汽车型号constmodel=car?.model??'defaultmodel';//获取厂家地址conststreet=car?.manufacturer?.address?.street??'defaultstreet';//检查汽车制造商是否来自美国对我来说,更好更干净,非常合乎逻辑。如果您想知道为什么要使用??而不是||,只要想想什么值可以被认为是真或假,你可能会有意想不到的输出。只是放在一边。自判断链接也支持DOMAPI,很酷,意思是你可以这样做:constvalue=document.querySelector('input#user-name')?.value;结论好吧,这就是它的全部内容。如果您喜欢这篇文章,请给我一杯咖啡提神,订阅这篇文章或在Twitter上关注我。