如何優雅地改善程式中for迴圈

2021-09-13 07:40:46 字數 3161 閱讀 1283

眾所周知,在我們的日常編碼裡,對於一些資料的迭代以及遍歷,首先想到的是for迴圈

這沒毛病,for迴圈編寫語法很簡單,只需要知道資料列表的長度即可進行遍歷取值,舉個例子:

有點程式設計基礎的童鞋,都可以很快想到上面的編寫方法。那不知道大家是否會跟我一樣對於寫for迴圈時,功能是沒毛病,但編寫起來總會覺得很不優雅,例如還要定義對應的i變數(拿上述舉例)以及還要自主控制i變數的變化,這樣無疑會變得繁瑣起來,也會讓我們編寫**效率有所下降

相信學過es6的童鞋,很快就會想到這種方法,下面我就拿上面的例子改造一下:

這種方式,看起來優雅了許多,省去了不必要的佇列長度對比變數的定義和控制以及佇列長度判斷

到這裡,foreach是不是就是最好的優雅方案?有沒有存在問題?,相信一部分童鞋未必能答出來,那我就不賣關子了。如果我們遇到一種情況,就是對列表遍歷處理後,需要返回乙個處理後的陣列,那我們繼續使用foreach是否能夠達到我們的目的呢?我們也許會有以下做法:

可以看到,第一種處理是希望處理完後直接賦值給乙個變數,然而foreach迴圈返回的是undefined,第二種處理雖然最終的確能夠達到我們目標,拿到處理完的資料,卻導致了乙個問題--全域性變數的汙染。當然也可以在外部定乙個陣列,然後push處理後的資料到新陣列來實現我們的目標,但整體看起來依然不是很優雅。

那有木有一種方法能夠返回乙個新陣列,並且又不會影響到原來的資料呢?答案是肯定的,這就要提到強大的functional programing(簡稱fp)

fp是什麼?又是用來幹什麼的?

functional programmings(fp) means coding in functions
這是比較簡潔和官方的說法,那是什麼意思?簡單地說,就是,用函式的方式處理問題,今天就會用到它的其中乙個核心思想:純函式(對於相同的輸入,永遠得到相同的輸出,而且不會有任何的***)看到這裡是不是有點頭緒了?,好啦,回到正題,那在js裡面有那些方法是純函式,而且又能優雅地替代for迴圈?相信童鞋們都會想到了map()

map方法會對原始陣列中的每個元素進行遍歷一次,並呼叫callback,最終返回乙個新的陣列而不會影響到原始陣列。

我們現在就拿上述foreach存在問題的栗子進行改造一下:

好明顯,曾經的多行迴圈**只需要一行就可以完成,看著也優雅了好多,而且返回乙個新的處理後的素組以及不會對原有的陣列產生汙染

filter方法,簡單滴說就是對陣列進行篩選或過濾,然後返回乙個新的陣列,並不會對原始陣列產生任何的影響

看到這裡,我們又要回到for迴圈那個栗子,使用filter方法是否可以讓**優雅起來?現在就來動手看看:

明顯,使用filter方法只能達到了第一步目標就是優雅了for迴圈裡的條件語句,那該怎麼辦?

我們會發現,filter方法是會返回乙個新陣列,那我們就可以聯絡到了map方法,兩者結合會產生什麼火花?

至此,是否會覺得看起來舒服好多,而且也通俗易懂,而這也是最終優雅方案。那麼問題來了,什麼時候該用foreach,什麼時候又該用map呢?

foreach比較適用於不改變原始陣列資料,僅僅拿陣列資料進行做一些事情,而map則適用於改變資料值並且返回乙個新陣列,當然不同情景又不同的做法,這僅僅只是作為乙個參考

除了上述提到的常用情景外,我們還會遇到很多其他地方可以繼續優雅for迴圈,這就不得不提some方法和every方法以及reduce方法(reduce也屬於fp)

every()和some()

現在有一種情景,就是要根據後端返回的乙個列表裡費用低於0時就展示提示語。結合上述學過的方法,也許我們會有以下做法:

除了上述比較的直接方法外,也許有些童鞋會想到直接使用foreach來進行優雅一下:

因為foreach處理資料是在callback上,因此使用break語法明顯會導致語法錯誤,因此,就算去掉break,也需要遍歷完所有元素,而主角來了,some和every:

明顯看著**量就簡潔了好多,而且也不失優雅。
reduce()可能有些童鞋對於reduce方法有點陌生,它究竟是用來幹嘛的?應用場景又是什麼?

reduce() 方法接收乙個函式作為累加器(accumulator),陣列中的每個值(從左到右)開始縮減,最終為乙個值
上面為官方的說法,簡單地理解,就是對乙個列表進行遍歷,第一次取兩個元素進行處理得到乙個新值,然後到下一次迴圈時就拿該新值與第三個元素進行處理,以此類推,最終得到乙個值並返回。文字太複雜,直接**:

是不是清晰很多了,那應用的優雅情景又有哪些?在這裡我就不賣關子了,例如,後端返回乙個物件,而我們需要對這個物件進行處理只需要得到指定屬性值,多餘的屬性就過濾掉。日常做法:

可以看到,雙層迴圈讓人看起來的確複雜很多,而且稍微不小心就會很容易出問題。然而使用reduce方法就可以優雅起來。

看了這個,是不是覺得reduce用了後特別簡潔和優雅。

如果你覺得它還不夠強大,再看看下面乙個栗子,就可以覺得它的厲害(這是額外話題了,大家有空可以研究一下)。我們經常會遇到一種情況就是,後端返回乙個巢狀很深的物件,然後前端拿到這個複雜的物件中某個屬性時,難免會需要每乙個值都要判斷是否存在,然後直到指定的屬性為止,這就是鏈式取值問題:

其實鏈式取值問題在網上有很多處理方案,那如果是最優雅方案,我覺得就是使用reduce,那麼使用reduce怎麼編寫呢?直接上圖

至此,對於for迴圈的優雅性,不同場景可以有很多的優雅方案(lodash等等),但我想說的是,原生js本身提供的api其實有很多方法是可以讓我們的程式變得便捷以及簡潔的,只有你多點用用它,就會體會到它的強大。哈哈,如果上文如果有不妥之處,歡迎各位大佬指點一下

實現乙個方法,計算出乙個字串中每個字元出現的次數?

方法我就不寫了,讓大家來一場頭腦風暴吧?

如何優雅地寫部落格

如何優雅地寫部落格 現在寫部落格面臨著幾個問題 編寫麻煩,大部分的部落格編輯器都很爛,csdn和等等。維護麻煩,維護多個部落格的資料同步很麻煩。歷史檢視,大部分部落格編寫都不能檢視之前的歷史資料。用github做部落格倉庫,將資料都寫在github上,這樣可以隨時檢視一年前的部落格資料,方便在原文件...

如何優雅地書寫JavaScript

這篇文章包含了幾乎所有關於提高 質量的內容,尤其是在構建大型應用程式時。主要包括四個部分 本主題僅涉及原生js,關於框架 比如react和vue 的內容會在以後的文章中展現。我想你們大多數人之前都聽說過solid,也就是物件導向設計裡的solid原則。這些原則基於物件導向設計,所以可能不適合其他程式...

如何優雅地關閉SparkStreaming

how to shutdown a spark streaming job gracefully 17 02 02 01 31 35 info streaming.streamingcontext invoking stop stopgracefully true from shutdown hoo...