[bug] JS sort 函數在 ios 中無效
首先,請原諒我做一次標題黨;
但我覺得從發現問題到最後解決問題的過程還是蠻有意思的,特此記錄一下;
背景
近兩天開發的航班延誤寶
是內嵌在客戶端(android、ios)webview 中的 H5 頁面。其中有部分內容需要前端排序後再顯示。代碼很簡單:
let m = [6,4,8,10,3,5]
console.log(‘排序前:‘, [6,4,8,10,3,5])
m.sort((a, b) => a < b)
console.log(‘排序後:‘, m)
ps:發現這段代碼的問題了麽?如果你知道原因,為了節省您寶貴的時間,後面內容就不要看啦;
在 PC 瀏覽器中打印的內容如下:
排序前: (6) [6, 4, 8, 10, 3, 5]
排序後: (6) [10, 8, 6, 5, 4, 3]
但我用 iPhone 進行測試(只測了IOS微信瀏覽器、IOS航班管家客戶端),卻有不一樣的體驗:
WTF!結果和沒排序一樣,為甚?
解決
最開始推測可能是 sort
存在兼容問題。於是,用插入排序替代sort
進行測試,結果正常。
後來,在張(zhen)老(da)師(tui)的指導下,了解了sort
的實現規範,才明白,原來是上面的實現有問題。
哪裏有問題?
在sort
實現的規範中有這麽一條:若 comparefn (a,b) === 0,則有 a === b 且 b === a 。
此時我們再看var comparefn = (a, b) => a < b
,它等同於var comparefn = (a, b) => a < b ? 1 : 0
。
它有一個隱藏的漏洞:當a >= b
時,comparefn(a,b) === 0
。而根據規範,通過comparefn(a,b) === 0
可以推測出a === b
,顯然這裏互相矛盾。
所以,我寫的這個comparefn
原本就是錯誤的,holyshit!
那麽正確的寫法應該是:var comparefn = (a, b) => b - a
。
完結撒花;
再問:為什麽android和ios對此表現的不一樣呢?應該是兩家在具體實現上有所不同。
更多:
array.prototype.sort 實現規範
[bug] JS sort 函數在 ios 中無效