# Javascript語言精粹之Array常用方法分析

## 1、Array常用方法分析

### 1.1 Array.prototype.sort()

Javascript的默認比較函數假定被排序元素都是字符串，所以直接調用sort方法，不能正確對數字數組排序

`var n=[3,11,6,23];n.sort();alert(n);//n: 11,23,3,6`

`var m=['aa',4,'b',12,2];m.sort(function(a,b){　　if(a===b){　　　　return 0;　　}　　if(typeof a === typeof b){　　　　return a<b ? -1 : 1;　　}　　return typeof a < typeof b ? -1 : 1;});alert(m);// 2,4,12,aa,b`

`var by=function(name){    return function(o,p){        var a,b;        if(o && p && typeof o === 'object' && typeof p ==='object'){            a=o[name];            b=p[name];            if(a===b){                return 0;            }            if(typeof a === typeof b){                return a<b ? -1 : 1;            }            return typeof a < typeof b ? -1: 1;        }else{            throw{                name:'error',                message:'expected an object when sorting by '+name            }        }            }};var s=[{first:'moe',last:'besser'},{first:'joe',last:'haha'},{first:'joe',last:'abc'}];s.sort(by('first'));s=[{first:'joe',last:'haha'},{first:'joe',last:'abc'},{first:'moe',last:'besser'}];`

`{first:'joe',last:'haha'}排在了{first:'joe',last:'abc'}`
`如果需要last為abc的對象排在前面，就需要基於多個key進行排序，此時可讓by第二個參數為一個比較函數`
`var by=function(name,minor){    return function(o,p){        var a,b;        if(o && p && typeof o === 'object' && typeof p ==='object'){            a=o[name];            b=p[name];            if(a===b){                return typeof minor === 'function' ? minor (o,p) : 0;            }            if(typeof a === typeof b){                return a<b ? -1 : 1;            }            return typeof a < typeof b ? -1: 1;        }else{            throw{                name:'error',                message:'expected an object when sorting by '+name            }        }            }};var s=[{first:'moe',last:'besser'},{first:'joe',last:'haha'},{first:'joe',last:'abc'}];s.sort(by('first',by('last')));s=[{first:'joe',last:'abc'},{first:'joe',last:'haha'},{first:'moe',last:'besser'}];};`

### 1.2 Array.prototype.splice()

array.splice(start,deleteCount,item...)方法從array中移除一個或多個元素，並用新的item替換他們。start是移除元素的開始位置，deleteCount是要移除的元素個數，如有額外插入的參數，這些item將被插入到所移除元素的位置上。返回一個包含被移除元素的數組。

`var a=['a','b','c'];var r=a.splice(1,1,'ache','bug');//a是['a','ache','bug','c']//r是['b']`

splice實現代碼和詳細解讀

`Array.prototype.splice=function(start,deleteCount){    var max=Math.max,        min=Math.min,        delta,//偏移量        element,        insertCount=max(arguments.length-2,0),//排除掉arguments參數中,start,deleteCount,剩余是待插入元素        k=0,        len=this.length,//對array調用時，this指向當前數組        new_len,        result=[],//返回數組        shift_count//需移位的數量;            start = start || 0;//start默認值為0    if(start<0) start+=len;//start<0時，從數組后端開始    start=max(min(start,len),0);//經過處理，0<=start<=len    deleteCount=typeof deleteCount === 'number' ? deleteCount : len;//deleteCount默認值是len    deleteCount=min(deleteCount,len-start);//deleteCount<=可刪除數量    deleteCount=max(deleteCount,0);//0<=deleteCount<=可刪除數量        delta=insertCount-deleteCount;    new_len=len+delta;        //獲取刪除元素    while(k<deleteCount){        element=this[start+k];        if(element!=undefined){            result[k]=element;        }        k +=1;    }    shift_count=len-start-deleteCount;    //待插入數量小於刪除數量，原數組后續元素依次向左偏移    if(delta<0){        k=start+insertCount;//從start至start+insertCount留給待插入元素        while(shift_count){            this[k]=this[k-delta];            k+=1;            shift_count-=1;        }        this.length=new_len;    }    //待插入數量大於刪除數量，原數組后續元素依次向右偏移    else if(delta>0){        k=1;        while(shift_count){            this[new_len-k]=this[len-k];            k+1;            shift_count-=1;        }        //this.length=new_len;非必須，因給一開始this[new_len-k]賦值時，length屬性已經自動設置為數組最后元素下標值    }    //delta===0 時，待插入數量等於刪除數量，無需偏移        //最后將待插入元素插入原數組    for(k=0;k<insertCount;k+=1){        this[start+k]=arguments[k+2];//排除掉arguments參數中start和deleteCount    }    return result;});`

### 1.3 Array.prototype.slice()

array.slice(start,end)方法是對array中一部分做淺復制，end參數可選，默認為array.length

`var a=['a','b','c'];var b=a.slice(0,1);//b是['a']var c=a.slice(1);//c是['b','c']alert(a);//['a','b','c']`

### 1.4 Array.prototype.push()、Array.prototype.pop()

push、pop方法可以實現棧的先進后出。

push(item...)方法將一個或多個參數item附加到一個數組的尾部，返回數組新的長度值

`var a=['a','b','c'];var b=[1,2];var c=a.push(b,true);//a=['a','b','c',[1,2],true];//c=5`

push方法實現和詳細解讀

`Array.prototype.push=function(){    //對arguments對象通過array.slice方法轉換成數組    var args=Array.prototype.slice.apply(arguments);    //通過array.concat，連接兩個數組    var params=[this.length,0].concat(args);    //對數組調用splice方法,start=this.length,deleteCount=0,insertItems=args    this.splice.apply(this,params);    //返回新的數組length    return this.length;});//上述步驟合並，簡寫為下面方式Array.prototype.push=function(){    this.splice.apply(        this,        [this.length,0].concat(Array.prototype.slice.apply(arguments)));    return this.length;    });`

pop方法移除array最后的一個元素並返回該元素，array為空時，返回undefined

`var a= ['a','b','c'];var c = a.pop();//a是['a','b'],c是'c'Array.prototype.pop=function(){  //start=this.length-1,deleteCount=1，結果數組的第[0]個元素    return this.splice(this.length-1,1)[0];    }`

### 1.5 Array.prototype.shift()、Array.prototype.unshift()

array.shift()方法移除數組array中第一個元素並返回該元素。數組為空時，返回undefined

`var a= ['a','b','c'];var c = a.pop();//a是['b','c'],c是'a'`

shift可以這樣實現

`Array.prototype.shift=function(){    //start=0,deletecount=1,返回結果數組中第[0]個元素    return this.splice(0,1)[0];}`

unshift將item插入array的開始部分

`var a = ['a','b','c'];var r=a.unshift('?','@');//a是['?','@','a','b','c'];//r是5`

unshift可以像這樣實現

`Array.prototype.unshift=function(){    //start=0,deleteCount=0,insertItems=arguments    this.splice.apply(this,    [0,0].concat(Array.prototype.slice.apply(arguments)));    return this.length;});`