A Blog

Array.prototype.sort 的無用雜談

December 24, 2019

Array.prototype.sort 應該大家再常用不過了吧?那麼你知道下面這行的結果是什麼嗎?

[1,3,2].sort((a,b) => a - b > 0)

丟到 Firefox,console 會『正常的』得出 [1, 2, 3]。 然而丟到 Chrome(>= v70),會得到 [1, 3, 2]…的『錯誤』結果。 再丟到 node 裡面,會發現直到 v10 之前的結果都是 [1, 2, 3],但到了 v12 就變成了 [1, 3, 2]

難不成瀏覽器 / node 有 bug?仔細一瞧,比較函數的回傳值怪怪的,應該是:

[1,3,2].sort((a,b) => a - b)

才對。重新丟回去執行,一切都回歸正常的 [1, 2, 3]了!

出錯的原因在於當我們的比較函數回傳的是 a - b > 0,那麼在 a 比 b 小時,則會回傳 false 而被轉型成 0,而不是負數,違背了 spec 的要求。

顯然這是開發者自己寫出來的 bug,可是為什麼剛好 Firefox / 舊版的 Chrome / node 在錯誤的比較函數下會得到正確的結果呢?我不明白 Array.prototype.sort 背後的實作細節,但已知 Chrome v70 / V8 v7.0 為了穩定排序結果,把 QuickSort 的實作換成了 TimSort,連帶的修正了這個問題。希望 Firefox 也能早日跟上。

題外話,IE / Edge 倒是一開始就做對了,真難得(?)


Yi-Shan, Chen

Written by Yi-Shan, Chen. Github