javascript Array對象

數組是一段線性分配的內存,它通過整數去計算偏移並訪問其中的元素。數組是很快的數據結構,但不幸的是,Javascript並沒有像這種數組一樣的數據結構。Javascript的數組實質是對象,它把數組的下標轉換成字符串,用其作爲屬性,因此它明顯比真正的數組慢,但它可以更方便地使用。

Array 對象的方法

FF: Firefox, N: Netscape, IE: Internet Explorer

方法描述FFNIE
concat() 向數組的副本添加新的元素,返回新的數組,原數組不受影響 1 4 4
join() 把數組的所有元素放入一個字符串。元素通過指定的分隔符進行分隔。 1 3 4
pop() 刪除並返回數組的最後一個元素 1 4 5.5
push() 向數組的末尾添加一個或更多元素,並返回新的長度。 1 4 5.5
reverse() 顛倒數組中元素的順序。 1 3 4
shift() 刪除並返回數組的第一個元素 1 4 5.5
slice() 從某個已有的數組返回選定的元素 1 4 4
sort() 對數組的元素進行排序,有一個可選參數,爲比較函數。 1 3 4
splice() 刪除元素,並向數組添加新元素。 1 4 5.5
toSource() 代表對象的源代碼 1 4 -
toString() 把數組轉換爲字符串,並返回結果。 1 3 4
toLocaleString() 把數組轉換爲本地數組,並返回結果。 1 3 4
unshift() 向數組的開頭添加一個或更多元素,並返回新的長度。 1 4 6
valueOf() 返回數組對象的原始值 1 2 4

Array 對象的屬性

方法描述FFNIE
index   1 3 4
input 在普通的Array中是不具備input屬性的,只有在調用String對象的match()方法後返回的數組才具有input屬性。它是用來存放匹配前的原字符串的內容。 1 3 4
length 設置或返回數組中元素的數目。 1 2 4

我們先來看數組克隆,現在公認用concat()來克隆數組的速度最快。下面做一些測試,分別爲直接遍歷複製,array.slice(0)與array.concat()

判斷一個變量引用的對象是否爲數組。

1.var isArray = function(a){
2.    return a &&
3.        typeof a === 'object' &&
4.        typeof a.length === 'number' &&
5.        typeof a.splice === 'function' &&
6.        !(a.propertyIsEnumerable('length'));
7.}

讓數組具有計算能力,這個也很常用,不要用於財會的特殊報表中。

01.Function.prototype.method = function(name,func){
02.    this.prototype[name] = func;
03.    return this;
04.}
05.Array.method('reduce',function(fn,value){
06.    for(var i=0,l=this.length;i<l;i++){
07.        value = fn(this[i],value);
08.    }
09.    return value;
10.});

如何使用,我們可以創建一個數字數組與相關的四則運算函數,把它們代入reduce函數中就行了

01.var data = [4,8,10,12,16]
02.var add = function(a,b){
03.    return a+b;
04.}
05.var mult = function(a,b){
06.    return a*b;
07.}
08.//使用
09.var sum = data.reduce(add,0)
10.var product = data.reduce(mult,1);

each方法,讓元素逐個執行傳入的方法。JavaScript 1.6裏已經實現了相應的forEach方法,但IE不支持,人們搞了個相近的each方法,在各大類庫都有相應的實現。我們看一個漂亮的實現(作者爲51JS的客服果果):

01.Array.prototype.each = function(fn){
02.    for (var i=0;i <this.length;i++)
03.        this[i].constructor==Array?
04.        this[i].each(fn):
05.        fn.call(this[i],i);
06.};
07.  
08.[1,[2,[3,[4,[5,[6,[7,[8,[9,[0]]]]]]]]]].each(
09.    function(){
10.        return alert(this);
11.    });

上面這個比較強大,除了能深層遍歷數組外,還能遍歷類數組對象(如arguments,NodeList),對象的所有屬性都會被fn方法進行調用。但是從設計模式來看,它承擔職責太多了.each方法就應該是面向數組,如果是對象或類數組對象,我們應該將它們轉化爲數組,如JQuery的makeArray,mootools和Prototype的$A。

1.var arrayize = function(iterable){
2.    if (iterable.item){
3.        var l = iterable.length || 0, array = new Array(l);
4.        while (l--) array[l] = iterable[l];
5.        return array;
6.    }
7.    return Array.prototype.slice.call(iterable);
8.};

接着下來我們就可以實現純數組的each函數了。

1.var each = function(func, array) {
2.  for (var i=0,l = array.length; i<l; ++i) {
3.      func(array[i])
4.  }
5.}

然後再改成一個原型方法

1.Array.prototype.each = function(func) { each(func,this); };

不過,如果瀏覽器支持javascript1.6的forEach方法,就用forEach

1.Array.prototype.each = function(func) {
2.    if(Array.prototype.forEach){
3.       this.forEach(func);
4.    }else{
5.        each(func,this); 
6.    }
7.};

用法:

1.[4, 5, 6].each(function(index) { alert(index + "+2 = " + (index+2)); })

火狐官網還有一個實現:

01.if (!Array.prototype.forEach)
02.{
03.  Array.prototype.forEach = function(fun /*, thisp*/)
04.  {
05.    var len = this.length >>> 0;
06.    if (typeof fun != "function")
07.      throw new TypeError();
08.  
09.    var thisp = arguments[1];
10.    for (var i = 0; i < len; i++)
11.    {
12.      if (i in this)
13.        fun.call(thisp, this[i], i, this);
14.    }
15.  };
16.}

讓我們看一下jQuery提供的each方法的具體實現

 jQuery.each(obj,fn,arg)   

該方法有三個參數:進行操作的對象obj,進行操作的函數fn,函數的參數args。

讓我們根據ojb對象進行討論:

1.obj對象是數組

each方法會對數組中子元素的逐個進行fn函數調用,直至調用某個子元素返回的結果爲false爲止,也就是說,我們可以在提供的fn函數進行處理,使之滿足一定條件後就退出each方法調用。當each方法提供了arg參數時,fn函數調用傳入的參數爲arg,否則爲:子元素索引,子元素本身。

2.obj 對象不是數組

該方法同1的最大區別是:fn方法會被逐次不考慮返回值的進行進行。換句話說,obj對象的所有屬性都會被fn方法進行調用,即使fn函數返回false。調用傳入的參數同1類似。

01.jQuery.each=function( obj, fn, args ) { 
02.    if ( args ) { 
03.       if ( obj.length == undefined ){ 
04.           for ( var i in obj ) 
05.             fn.apply( obj, args ); 
06.       }else
07.           for ( var i = 0, ol = obj.length; i < ol; i++ ) {
08.              if ( fn.apply( obj, args ) === false
09.                  break
10.          }
11.       }
12.   } else
13.       if ( obj.length == undefined ) {
14.            for ( var i in obj ) 
15.               fn.call( obj, i, obj ); 
16.       }else
17.          for ( var i = 0, ol = obj.length, val = obj[0]; i < ol && fn.call(val,i,val) !== false; val = obj[++i] ){} 
18.       }
19.  
20.  return obj; 
21.}

需要特別注意的是each方法中fn的具體調用方法並不是採用簡單的fn(i,val)或fn(args),而是採用了fn.call(val,i,val)或fn.apply(obj.args)的形式,這意味着,在你自己的fn的實現中,可以直接採用this指針引用數組或是對象的子元素。這種方式是絕大多數jQuery所採用的一種實現方式。

01.Array.prototype.distinct = function(){
02.    var self = this;
03.    var arr = [];
04.    for(var i=0,l = self.length;i<l;i++){
05.        for(var j=0,ll=arr.length;j<ll;i++){
06.            if(arr[j] != self[j]){
07.                arr.push(self[j]);
08.            }
09.        }
10.    }
11.    return arr;
12.}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章