基於原生JS封裝數組原型上的sort方法

基於原生JS封裝數組原型上的sort方法

最近學習了數組的原型上內置方法的封裝,增強了用原生JS封裝方法的能力,也進一步理解數組方法封裝的過程,實現的功能。雖然沒有深刻底層,瞭解源碼。如下解法都是基於我的理解用純原生JS實現的功能。若有不對的地方,能夠評論告訴我喲javascript

首先,咱們先來看一下sort方法的做用、參數、以及方法的返回值,原有數組是否發生改變java

sort方法主要用於數組的排序
參數分爲兩種:數組

  • 一種:傳的參數是函數、 (排序主要看函數的返回值)
  • 另外一種:傳的不是函數、或者不傳(只要傳的不是函數就對原來排序過程不產生影響)
    方法的返回值是原來數組排序後的數組
    原來數組發生改變,是排序後的數組

其次,咱們來看一下sort方法要處理的各類狀況之間的比較函數

狀況1:無參實現對字符串數組的排序
狀況2:無參實現對number類型的數組進行排序
狀況3:無參實現對字符串、number等混合類型的數組的排序
狀況4:帶參實現對number類型的數值數據排序
狀況5:帶參sort()對簡單對象List的自定義屬性排序
狀況6:帶參實現對字符串、number混合類型的數組的排序學習

sort方法對參數的處理:this

狀況1:若是參數不是函數,則不影響原來排序過程
狀況2:若是參數是函數,則根據回調函數中的返回值進行排序。若是返回值大於0,則交換位置;若是返回值小於0,則不交換位置
若是返回值不是一個數字,則不交換位置prototype

基於以上狀況的討論,sort方法實現的核心原理以下:3d

核心原理:不帶參(以及帶的參數不是函數)的狀況下:默認升序排列
不帶參的狀況下,直接轉字符串,逐個比較ASCII碼的值
只要有一個是對象{}就不交換
帶參數爲函數的狀況下:
根據函數的返回值進行比較;若是函數返回值大於0;則交換位置code

實現代碼以下:

Array.prototype.mySort = function(fn){
    if(Object.prototype.toString.call(fn)==='[object Function]'){
        //若是傳進來參數的是函數
        for(var i = 0;i<this.length-1;i++){
            //遍歷數組,將先後兩項做爲實參傳給fn
            if(fn.call(this,this[i],this[i+1])>0){
                //若是fn執行以後的返回值大於0.就調用swap方法交換位置
                var a = this[i],b=this[i+1];
                this[i] = swap(a,b).a;
                this[i+1] = swap(a,b).b;
                //交換以後,若是當前項不是第一項,則當前項(索引爲i的項)繼續跟前面的項進行比較
                if(i>0){
                    for(var j = i-1;j>=0;j--){
                            if(fn.call(this,this[j],this[j+1])>0){
                                var a = this[j],b=this[j+1];
                                this[j] = swap(a,b).a;
                                this[j+1] = swap(a,b).b;
                            }
                        }
                }
            }
        }
    }else{
        //若是不是函數,則按正常排序
        //遍歷數組,將先後兩項進行比較
        for(var i = 0;i<this.length-1;i++){
            var cur = this[i];//當前項
            var next = this[i+1];//下一項
            if(comASCII(cur,next)){
                //當返回true的時候交換,而且交換完成以後,當前項繼續往前比較
                this[i] = swap(cur,next).a;
                this[i+1] = swap(cur,next).b;
                //當前項繼續向前比較
                if(i>0){
                    for(var k = i-1;k>=0;k--){
                        var cur = this[k];
                        var next = this[k+1];
                        if(comASCII(cur,next)){
                            this[k] = swap(cur,next).a;
                            this[k+1] = swap(cur,next).b;
                        }
                    }
                }
            }
        }
    }
    //封裝一個交換位置的函數
    function swap(a,b){
        return {
            a:b,
            b:a
        }
    }
    //若是不傳參的狀況下比較ASCII碼
    function comASCII(cur,next){
        //所有轉換爲字符串、逐項比較ASCII碼
        cur = cur.toString();
        next = next.toString();
        //取長度最大值
        var len = cur.length>next.length?next.length:cur.length;
        //當先後兩項都不是否是{}類型的數據時,進行比較
        if(cur!=='[object Object]'&&next!=='[object Object]'){
            for(var j = 0;j<len;j++){
                if(!isNaN(cur.charCodeAt(j))&&!isNaN(next.charCodeAt(j))){
                    //若是兩者的ASCII碼都是有效數字
                    if(cur.charCodeAt(j)>next.charCodeAt(j)){
                        //若是前一項比後一項當前的ASCII碼大,則返回true,交換位置
                        return true;
                    }else if(cur.charCodeAt(j)==next.charCodeAt(j)){
                    //若是相等直接進入下一輪循環
                            continue;
                        }else{
                        //前項比後項小,直接返回false
                            return false;
                        }
                }
            }
            if(!isNaN(cur.charCodeAt(len))&&isNaN(next.charCodeAt(len))&&(cur.charCodeAt(len-1)==next.charCodeAt(len-1))){
                //比較完以後,若是前一項ASCII仍是有效數字,說明前項比後項大,交換
                return true;
            }
        }
        //若是上述條件不知足,則不交換
        return false;
    }
    //返回當前數組
    return this;
};

實驗結果

無參(參數非函數)對純數字數組的排序

帶參對純數字數組的排序(升序)

帶參對純數字數組的排序(降序)

無參(參數非函數)對純字母字符串數組的排序

帶參(參數是函數)對純字母字符串數組的排序(升序)

帶參(參數是函數)對純字母字符串數組的排序(降序)

無參(參數非函數)對純字母字符串、數字字母組合字符串、純數字字符串組合的排序

帶參(參數是函數)對純字母字符串、純數字、數字字母字符串、純數字字符串等的組合排序結果(升序)

帶參(參數是函數)對純字母字符串、純數字、數字字母字符串、純數字字符串等的組合排序結果(降序)

無參(參數非函數)對純字母字符串、純數字、數字字母字符串、純數字字符串等的組合排序結果

帶參(參數是函數)對純字母字符串、純數字、數字字母字符串、純數字字符串等的組合排序結果(升序)

帶參(參數是函數)對純字母字符串、純數字、數字字母字符串、純數字字符串等的組合排序結果(降序)

無參(參數非函數)對數組、純字母字符串、純數字、數字字母字符串、純數字字符串等的排序

帶參(參數是函數)對數組、純字母字符串、純數字、數字字母字符串、純數字字符串等的排序(升序)

帶參(參數是函數)對數組、純字母字符串、純數字、數字字母字符串、純數字字符串等的排序(降序)

帶參(參數是函數)對純數組的排序(升序)

帶參(參數是函數)對純數組的排序(降序)

帶參(參數是函數)對純對象的排序(升序)

帶參(參數是函數)對純對象的排序(降序)

相關文章
相關標籤/搜索