【譯】為什么我更喜歡對象而不是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.pswp.cn/news/275726.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275726.shtml
英文地址,請注明出處:http://en.pswp.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;高通…