最近學習了數組的原型上內置方法的封裝,增強了用原生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; };
實驗結果