經常使用瀏覽器排序源碼解析

常見問題

不少人在使用sort時,確定這樣寫過:javascript

[1, 2, 5, 40].sort()
>> [1, 2, 40, 5]

顯然結果是不符合指望的,爲何會這樣呢,咱們先來看下ECMAScript標準。java

ECMAScript標準

sort方法的參數

可選參數: compareFunction數組

形式:function (a, b) {瀏覽器

​ // need return numberide

​ }編碼

未傳入compareFunction時

1 將須要比較的值轉換爲字符串;spa

2 按照UTF-16編碼,升序排序。code

已傳入compareFunction時

compareFunction(a, b) {blog

​ return < 0 // a排在b前面排序

​ return === 0 // a和b這次不交換位置

​ return > 0 // b在a前面

}

空元素處理

undefined、empty、null元素都移到數組最後,且不參與比較。

根據ECMAScript標準的定義,不傳入compareFunction時,數組元素被看成字符串進行排序了,因此會出現不符合指望的結果。

瀏覽器實現

Firefox - SpiderMonkey

主流程

spider_1.png

1 ToBoject:

​ 調用C++方法,將數組轉換成Object;

2 ArrayNativeSort(C++)排序;

3 若是2失敗,使用js的排序方法排序。

ArrayNativeSort(C++)

spider_2.png

1 MergeSort:

​ 使用自底向上的歸併排序;

​ 對於length <= 3的小數組,使用插入排序;

2 MoveHoles:

​ 將數組中的空元素移動到數組末尾。

js實現的排序

spider_3.png

MergeSort:

​ length < 24,使用插入排序;

​ length >= 24,使用自底向上的歸併排序,初始sz = 4,使用插入排序初始化,使數組局部有序。

Chrome - v8

主流程

v8_1.png

1 TO_OBJECT:

​ 調用C++方法,將數組轉換成Object;

​ 移動空元素至數組末尾;

2 若是未傳入compareFunction,將compareFunction置爲C++的SmiLexicographicCompare方法;

3 排序。

排序

v8_2.png

length <= 10,插入排序;

length > 10,快速排序和插入排序的混合排序。

Safari - JavaScriptCore

主流程

core_1.png

1 toObject:

​ 將數組轉換成Object;

2 compact:

​ 移動空元素至數組末尾;

3 排序

排序

bucketSort(未傳入compareFunction):
core_2.png

​ 桶排序,使每一個桶大小 < 32;

​ 每一個桶中使用歸併排序。

mergeSort(已傳入compareFunction):
core_3.png

​ 自底向上的歸併排序

應用

數字數組排序

使用sort給數字數組排序時,注意必須傳入compareFunction

穩定的排序

有時,咱們但願數組中重複元素排序先後的相對位置不發生變化,咱們就須要使用穩定的排序,例如插入、歸併排序;

可是,ECMAScript標準並未規定瀏覽器是否須要實現穩定的排序,這時,咱們須要藉助第三方庫或者本身實現排序。

相關文章
相關標籤/搜索