首頁 > 藝術

淺談 JavaScript 中 sort( ) 排序的坑

由 4位元組 發表于 藝術2023-01-28

簡介基本排序JS 中的 Array 物件有一個排序方法 sort( ),呼叫它的執行結果一般來說是這樣的:甚至當陣列中出現未定義值的元素時 sort( ) 也同樣好用

陣列未定義的會預設為什麼

淺談 JavaScript 中 sort( ) 排序的坑

Array 陣列的排序受關注度一直就不高,除非當它出現了問題。最近我在專案中就遇到了一個數組排序問題,陣列中的項沒有按我預想的被排序,導致介面上無法正常顯示。我花了很長的時間才明白問題究竟出在哪裡,所以想在這裡和大家分享一下。

基本排序

JS 中的 Array 物件有一個排序方法 sort( ),呼叫它的執行結果一般來說是這樣的:

淺談 JavaScript 中 sort( ) 排序的坑

甚至當陣列中出現未定義值的元素時 sort( ) 也同樣好用。文件中有這樣一句話:

“所有未定義的陣列元素都會被轉化成字串,並透過比較 UTF-16 的值來進行排序。”https://developer。mozilla。org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

淺談 JavaScript 中 sort( ) 排序的坑

一些陷阱

使用排序時你可能會遇到的第一個問題就是當陣列中有 null 時。排序方法會強行把空值轉換成字串“null”,而 n 位於字母表大概中間的一個位置。

淺談 JavaScript 中 sort( ) 排序的坑

然後就是數字。排序方法的預設演算法是將陣列內全部元素轉成一個字串陣列,再

比較它們的 UTF-16 編碼

。如之前所見,在元素為字串時這個方法很好用,但碰見數字元素時就尷尬了。

淺談 JavaScript 中 sort( ) 排序的坑

如上圖所示,在這個例子中執行結果裡 10 排在 3 之前,因為字串“10”排在字串“3”之前。

我們可以透過給 JS 提供一個用於排序的比較函式來解決這個問題。函式從陣列物件中接收兩個元素並返回一個數字的值,該值是大於,小於或是等於零決定了這兩個數字排序時的位置。比方說如果返回值為負數,第一個元素就會被排在第二個元素之前,如果值為0則證明兩個元素等值。

要升序排列這些數字,函式的寫法很簡單。用兩個元素相減,符合我們的描述,最終也會得出正確的排序。我們把這個函式提供給 JS 排序的方法,和下圖中一樣:

淺談 JavaScript 中 sort( ) 排序的坑

淺談 JavaScript 中 sort( ) 排序的坑

注意這個解決方案同樣適用於當有元素未定義時,因為未定義元素預設排在末尾。

淺談 JavaScript 中 sort( ) 排序的坑

不過 null 仍然是一個問題。

淺談 JavaScript 中 sort( ) 排序的坑

因為將 null 放入數字轉換方法中得到的是 0。

淺談 JavaScript 中 sort( ) 排序的坑

你可以透過再次改進之前所寫的 compareNumbers 函式,或者勉強繼續使用。

排序結果不一致性

最大的問題,也就是最近我才發現的問題,就是當 undefined 未定義以其它的方式進入到陣列中。之前我們已經知道如果有未定義的元素,它預設會被排到末尾。然而如果被排序的物件,鍵是未定義的話,出現的結果就會不一致。

比方說,你有一個物件陣列,其中一些物件有值,一些物件沒有,排序的結果可能與你的預期產生偏差。

淺談 JavaScript 中 sort( ) 排序的坑

用 undefined 減去一個數字或者用數字減去 undefined 都會返回 NaN,NaN 並不在數字比較方法返回值的範圍中,因為它或為正或為負或等於0,所以最後的排序結果會很奇怪。本例中,引發問題的元素位置不變,該元素上下的數字僅僅被區域性排序。

這個問題的解決方法有幾個,但重要的就是我們需要知道它是有可能發生的。在我的專案中,我直接過濾掉了沒有值的陣列元素。

淺談 JavaScript 中 sort( ) 排序的坑

結論

上文分析的結果就在於 sort( ) 排序方法並不如我們所想象的那麼直接和易用。字串排序沒有問題,數字排序需要額外的操作但也能實現,雖然方法本身對 undefined 已經有處理方法,但我們必須格外小心對 undefined 和 null 物件的強制轉型。

微信搜尋 “ng_4bytes” 關注4位元組官方微訊號,獲取IT界一手資訊,更有免費程式設計師培訓課程等你來拿!

Tags:排序元素陣列未定義數字