【译】为什么我更喜欢对象而不是switch语句

原文自工程师Enmanuel Durán博客,传送门

最近(或者不是最近,这完全取决于您什么时候阅读这边文章),我正在跟我的团队伙伴讨论如何去处理这种需要根据不同的值去处理不同的情况的方法,通常对于这种情况下,人们喜欢使用switch语句或者使用很多if搭配else if条件。在本文中我将重点介绍第三种方式(我更为喜欢的方法),即使用对象进行快速地查找。

switch 语句

switch语句允许我们根据传递的表达式的值来执行表达式并执行某些特定的操作,通常当你学习编写代码和算法时,你会发现可以将它专门用于多种值的情况,你开始使用它,它看起来很好,你很快意识到它给了你很大的自由,耶!但是要小心,自由度越大责任感也就越大。

让我们快速了解一下典型的switch语句是怎么样的:

switch (expression) {case x: {/* Your code here */break;}case y: {/* Your code here */break;}default: {/* Your code here */}
}

很好,现在有一些你可能不知道需要注意的事情:

可选的关键字break

break关键字允许我们在满足条件时停止执行块。如果不将break关键字添加到switch语句,则不会抛出错误。如果我们不小心忘记break的话,可能意味着在执行代码的时候你甚至不知道代码已经正在执行中了,这还会在调试问题时增加实现结果的的不一致性、突变、内存泄漏和复杂度等问题。我们来看看这个问题的一种表示形式:

switch ('first') {case 'first': {console.log('first case');}case 'second': {console.log('second case');}case 'third': {console.log('third case');break;}default: {console.log('infinite');}
}

如果你在控制台中执行这段代码,你会看到输出是

firt case
second case
third case

switch语句在第二种和第三种情况下也会执行,即使第一种情况已经是正确的,然后它在第三种情况块中找到关键字break并停止执行,控制台中没有警告或错误让你知道它,这会让你认为这是预期的行为。

每种情况下的大括号都不是强制的

在javascript中大括号代表着代码块,因为自ECMAscript 2015我们可以使用关键字声明块编译变量,如const或let(但对于switch来说并不是很好),因为大括号不是强制性的,重复声明会导致错误变量,让我们看看当我们执行下面的代码时会发生什么:

switch ('second') {case 'first':let position = 'first';console.log(position);break;case 'second':let position = 'second';console.log(position);break;default:console.log('infinite');
}

我们会得到:

Uncaught SyntaxError: Identifier 'position' has already been declared

这里将会返回一个错误,因为变量position已经在第一种情况下声明过了,并且由于它没有大括号,所以在第二种情况下尝试声明它,它已经存在了。

现在想象使用带有不一致break关键字和大括号的switch语句时会发生什么事:

switch ('first') {case 'first':let position = 'first';console.log(position);case 'second':console.log(`second has access to ${position}`);position = 'second';console.log(position);default:console.log('infinite');
}

控制台将输出以下内容:

first
second has access to first
second
infinite

试想一下,由此而引起的错误和突变是如此之多,其可能性是无穷无尽的……不管怎样,switch语句已经讲够了,我们来这里是为了讨论一种不同的方法,我们来这里是为了讨论对象。

更安全查找的对象

对象查找速度很快,随着它们的大小增长它们也会更快,它们也允许我们将数据表示为对于条件执行非常有用的键值对。

使用字符串

让我们从简单的switch示例开始,让我们假设我们需要有条件地保存和返回一个字符串的情景,并使用我们的对象:

const getPosition = position => {const positions = {first: 'first',second: 'second',third: 'third',default: 'infinite'};return positions[position] || positions.default;
};const position = getPosition('first'); // Returns 'first'
const otherValue = getPosition('fourth'); // Returns 'infinite'

这可以做同样类型的工作,如果你想进一步的压缩简化代码,我们可以利用箭头函数:

const getPosition = position =>({first: 'first',second: 'second',third: 'third'}[position] || 'infinite');const positionValue = getPosition('first'); // Returns 'first'
const otherValue = getPosition('fourth'); // Returns 'infinite'

这与前面的实现完全相同,我们在更少的代码行中实现了更紧凑的解决方案。

现在让我们更实际一点,不是我们写的所有条件都会返回简单的字符串,其中很多会返回布尔值,执行函数等等。

使用布尔值

我喜欢创建返回类型一致的值的函数,但是,由于javascript是动态类型语言,因此可能存在函数可能返回动态类型的情况,因此我将在此示例中考虑这一点,如果找不到键,我将创建一个返回布尔值,未定义或字符串的函数。

const isNotOpenSource = language =>({vscode: false,sublimetext: true,neovim: false,fakeEditor: undefined}[language] || 'unknown');const sublimeState = isNotOpenSource('sublimetext'); // Returns true

看起来不错,对吧?别急,好像我们有一个问题......如果我们调用带有参数的函数,会发生什么'vscode'或fakeEditor不是?嗯,让我们来看看:

  1. 它会寻找对象中的键。
  2. 它会看到vscode键的值是false。
  3. 它会试图返回false,但因为false || 'unknown'是unknown,我们最终会返回一个不正确的值。

对于key为fakeEditor也会有同样的问题

Oh no, 好吧,不要惊慌,让我们来解决这个问题:

const isNotOpenSource = editor => {const editors = {vscode: false,sublimetext: true,neovim: false,fakeEditor: undefined,default: 'unknown'};return editor in editors ? editors[editor] : editors.default;
};const codeState = isNotOpenSource('vscode'); // Returns false
const fakeEditorState = isNotOpenSource('fakeEditor'); // Returns undefined
const sublimeState = isNotOpenSource('sublimetext'); // Returns true
const webstormState = isNotOpenSource('webstorm'); // Returns 'unknown'

这就解决了问题,但是......我希望你们问自己一件事:这真的是问题所在吗?我认为我们应该更关心为什么我们需要一个返回布尔值,未定义值或字符串的函数,这里存在严重的不一致性,无论如何,对于这样一个非常棘手的情况这也只是一个可能的解决方案。

使用函数

我们继续讲函数,通常我们会发现我们需要根据参数来执行一个函数,假设我们需要根据输入的类型来解析一些输入值,如果解析器没有注册,我们只返回值:

const getParsedInputValue = type => {const emailParser = email => `email,  ${email}`;const passwordParser = password => `password, ${password}`;const birthdateParser = date => `date , ${date}`;const parsers = {email: emailParser,password: passwordParser,birthdate: birthdateParser,default: value => value};return parsers[type] || parsers.default;
};// We select the parser with the type and then passed the dynamic value to parse
const parsedEmail = getParsedInputValue('email')('myemail@gmail.com'); // Returns email, myemail@gmail.com
const parsedName = getParsedInputValue('name')('Enmanuel'); // Returns 'Enmanuel'

如果我们有一个类似的函数返回另一个函数但这次没有参数,我们可以改进代码,以便在调用第一个函数时直接返回,如:

const getValue = type => {const email = () => 'myemail@gmail.com';const password = () => '12345';const parsers = {email,password,default: () => 'default'};return (parsers[type] || parsers.default)(); // we immediately invoke the function here
};const emailValue = getValue('email'); // Returns myemail@gmail.com
const passwordValue = getValue('name'); // Returns default

通用代码块

Switch语句允许我们为多个条件定义公共代码块。

switch (editor) {case 'atom':case 'sublime':case 'vscode':return 'It is a code editor';break;case 'webstorm':case 'pycharm':return 'It is an IDE';break;default:return 'unknown';
}

我们如何使用对象来处理它?我们可以在下一个方面做到这一点:

const getEditorType = type => {const itsCodeEditor = () => 'It is a code editor';const itsIDE = () => 'It is an IDE';const editors = {atom: itsCodeEditor,sublime: itsCodeEditor,vscode: itsCodeEditor,webstorm: itsIDE,pycharm: itsIDE,default: () => 'unknown'};return (editors[type] || editors.default)();
};const vscodeType = getEditorType('vscode'); 

现在我们有一种方法:

  1. 更有条理
  2. 更易拓展
  3. 更容易维护
  4. 更容易测试
  5. 更安全并且副作用和风险更小

注意事项

正如预期的那样,所有的方法都有其缺点,这一个也不例外。

  1. 由于我们正在使用对象,所以我们将占用内存中的一些临时空间来存储它们,当定义对象的作用域不再可访问时,这个空间将被垃圾收集器释放。
  2. 当没有太多情况需要处理时,对象方法可能比switch语句的速度要慢,这可能是因为我们正在创建一个数据结构,然后接收一个键,然而在switch中,我们只是检查值并返回值。

结论

本文不打算改变你的编码风格或让你停止使用switch语句,它只是试图提高你对switch语句的认识,以便它可以正确使用,并开放你的思想探索新的替代方案,在这种情况下,我已经分享了我喜欢使用的方法,但还有更多,例如,你可能想看一个称为模式匹配的ES6提案,如果你不喜欢它,你可以继续探索。

好的开发未来,就是这样,我希望你喜欢这篇文章,如果你这样做,你可能会喜欢这篇关于工厂模式的文章。此外,不要忘记分享和点赞,你可以在twitter上找到我或通过我的电子邮件duranenmanuel@gmail.com联系我,下一个见。

阅读EnmaScript.com上发布的原始文章

译者总结

本文介绍了一种使用对象去代替我们之前用switch和繁琐的if else语句的方法。其实,很多情况下我们可以利用对象与其他组合搭配写出更为高效或可维护的代码。当然,如何去灵活地使用对象去处理一些对应的情况,还是靠我们自己。好的,这篇就总结到这了,不知道对你们有什么启发。相信会给到一些帮助给读者,我们可不是一个只会if else的工程师,哈哈~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

摩托罗拉周二将正式分拆为两经营实体

据华尔街中文网消息称,摩托罗拉公司周二将正式分拆为两个经营实体——摩托罗拉移动控股(MMI)和摩托罗拉解决方案公司(MSI)。前者由主要面向消费者的智能手机和机机顶盒业务组成,后者则专注于公共安全无线电和手持扫描仪业务。 上述两家公司的股票均已于…

如何创建和谐的色彩系统

拥有和谐的色彩系统的好处 (The benefits of having a harmonious color system) Consistent branding express across all platform 在所有平台上表达一致的品牌 The consistent interface creates a better user experience 一致的界面创建了更好的用户体验 More productive …

java restful接口测试_详解SpringBoot restful api的单元测试

现在我们来利用Spring Boot来构建一个RestFul API,具体如下:1.添加Springboot测试注解RunWith(SpringRunner.class)SpringBootTestpublic class UserControllerTest {}2.伪造mvc环境// 注入Spring 工厂Autowiredprivate WebApplicationContext wac;//伪造…

老姚浅谈:怎么学JavaScript?

大家好,我是若川。当初我就是看本文深受启发,开始看书读源码。所以现在联系了作者老姚 授权转载分享给大家。我按照文中的做法敲完了《JavaScript语言精粹 修订版》,在2017年7月23日写出了我的第一篇文章《读书笔记》。看完了《JavaScript面向…

JavaScript 如何使用闭包

闭包基本上是内部函数可以访问其范围之外的变量&#xff0c;可用于实现隐私和创建函数工厂 定义一个数组&#xff0c;循环遍历这个数组并在延迟3秒后打印每个元素的索引 先看一个不正确的写法&#xff1a; const arr [10, 12, 15, 21]; for (var i 0; i < arr.length; i) …

ai中导入sketch_在Sketch中营造深度感

ai中导入sketchCreating a user interface with depth can seem daunting at first, but it only requires you to understand one fundamental rule — emulating a light source.首先&#xff0c;创建具有深度的用户界面似乎很艰巨&#xff0c;但这仅要求您了解一个基本规则-…

java byte转bigdecimal_Java BigDecimal byteValueExact()用法及代码示例

java.math.BigDecimal.byteValueExact()是一个内置函数&#xff0c;它将BigDecimal转换为字节并检查丢失的信息。任何大于127或小于-128的BigDecimal值都将生成异常&#xff0c;因为它不适合字节范围。用法:public byte byteValueExact()参数&#xff1a;该方法不接受任何参数。…

Python3+PyCharm+selenium3 环境搭建

安装Python3请去python官网下载安装包&#xff0c;我用的是Python3.6安装PyCharm&#xff0c;这个也是去官网自己下吧&#xff0c;偶的是2018.2.3&#xff08;CommunityEdition&#xff09;接下来安装seleniumPyCharm中Tremianl安装完成后&#xff0c;在python Console中输入没…

2021 年最值得了解的 Node.js 工具

大家好&#xff0c;我是若川。今天分享一篇用得上的 node 库 链接地址&#xff1a;https://github.com/huaize2020/awesome-nodejs❝前言&#xff1a;文章的灵感来源于&#xff0c;社群中某大佬分享一个自己耗时数月维护的github项目 awesome-nodejs 。或许你跟我一样会有一个疑…

DOMContentLoaded与interactive

ie中inline script执行时竟然第一次进入页面,doc.readyState是interactive.刷新则是loadinginteractive也就算了,竟然没有把dom树构建好,也没有body...而在inline的脚本里跑计时器什么的,去doc.body.doScroll(left);则有可能碰到interactive时dom树构建好的情况.而其它浏览器in…

figma下载_何时在Figma中使用组或框架

figma下载Groups and Frames have very different uses in Figma, but it’s difficult at first to tell why both of them exist. I can assure you that they complement each other, but first, you need to understand the nuances of each. I’ll show you how to make t…

java标记错误_标记电子邮件Java时出错

在调用以下我的代码片段时&#xff1a;Message message_in null;inbox instanceof IMAPFolderIMAPFolder f (IMAPFolder)inbox;f.idle();System.out.println("IDLE done");message_in inbox.getMessage(inbox.getMessageCount());message_in.setFlag(Flags.Flag.D…

迈入现代 Web 开发(GMTC 2021 演讲全文)

前言&#xff1a;希望像做游戏一样做 Web 开发的 dexteryy 同学今天在 GMTC 技术大会上又搞了一场「跨年演讲」&#xff08;内容超多的意思&#xff09;&#xff0c;不但现场爆满、超时严重&#xff0c;而且一如既往的讲完之后只要把讲稿和幻灯片拼起来就能发出来&#xff0c;大…

Laravel 测试: PHPUnit 入门教程

介绍 PHPUnit 测试的基础知识&#xff0c;使用基本的 PHPUnit 断言和 Laravel 测试助手。 介绍 PHPUnit 是最古老和最著名的 PHP 单元测试包之一。它主要用于单元测试&#xff0c;这意味着可以用尽可能小的组件测试代码&#xff0c;但是它也非常灵活&#xff0c;可以用于很多不…

Brad Wilson写的 ASP.NET MVC 3 Service Location 系列文章索引

Brad Wilson在他自己的博客写了有关ASP.NET MVC3依赖注入支持的一系列文章&#xff0c;但由于某些原因&#xff08;你懂的&#xff09;&#xff0c;需要FQ才能阅读。 为了方便自己也方便喜欢的同学&#xff0c;特意FQ再拷贝回来发布&#xff0c;以下是这一系列文章的索引&#…

注释标记的原则_它关系到平台如何标记操纵的媒体。 这是设计师应遵循的12条原则。

注释标记的原则By Emily Saltz, Tommy Shane, Victoria Kwan, Claire Leibowicz, Claire Wardle埃米莉萨尔茨 ( Emily Saltz) &#xff0c; 汤米沙恩 ( Tommy Shane) &#xff0c; 关 颖琳 ( Victoria Kwan) &#xff0c; 克莱尔莱博维奇 ( Claire Leibowicz) &#xff0c; 克莱…

saltapi java_搭建基于Jenkins salt-api的运维工具

1. 安装salt-master和salt-minion安装过程不再赘述&#xff0c;请参考http://docs.saltstack.com/en/latest/topics/installation/index.html2. 安装salt-api&#xff0c;cherrypy用来jenkins与salt通信启用salt-api在salt master的配置文件中添加rest_cherrypy:port: 8010host…

他开发了redux,昨晚字节一面却挂了?

大家好&#xff0c;我是若川&#xff0c;诚邀你进群交流学习。今天分享一次直播的记录。我写过redux源码文章。动手按照文中例子学习&#xff0c;我相信会有所收获。学习源码系列、面试、年度总结、JS基础系列redux的作者是谁&#xff1f;Dan&#xff0c;他的全称叫做Dan Abram…

Onew积极开拓国际市场,为全球用户提供全方位金融服务

当区块链技术刚被提出的时候&#xff0c;金融被认为是最主要的应用场景之一&#xff0c;具体包括建立基于区块链技术的银行间点对点支付结算系统和跨境支付系统、在交易所运用区块链技术实现股权的登记和转让等。 区块链应用于金融领域有着天生的绝对优势&#xff0c;主观来看&…

高通董事长:努力降低智能手机价格

高通董事长&#xff1a;努力降低智能手机价格 高通公司董事长兼CEO保罗雅各布近日表示&#xff0c;2011年高通除了继续与各方合作提供高端及各层次智能手机外&#xff0c;将更加致力于降低智能手机的价格。 手机将成为个人生活中心 作为移动通信芯片领域的霸主&#xff0c;高通…