JavaScript中Array

数组是一段线性的数据结构,这种数据结构一般来说是很快的,但不幸的是,JavaScript中并没有这种数据结构。

然后,JavaScript提供了一种类似数组(array-like)的结构。它把数组的下标转变成字符串,用其作为属性。正因为如此,它会比真正的数组要慢,但是并不影响其使用。

1.数组字面量

数组字面量提供了一种非常方便的创建新数组的表示法。

代码
    var empty = [];
    
var numbers = [
         
'zero','one','two',
         
'three','four'
    ]
    empty[
1//undefined
    numbers[1]    //'one'
    empty.length //0
    numbers.length //5
 

当然,与其他语言类似,JavaScript中数组的"下标"是从0开始的。另外,也可以有另外一种方式创建数组:

var array = new Array();

在实际中,普遍会采用第一种创建数组的方式,因为第一种方式更为简洁,速度也更快。

与该数组字面量对应的是一个对象字面量:

    var number_object = {
       
'0':'zero','1':'one','2':'two'
       
'3':'three','4':'four'    
    };

numbers与number_object都是包含5个属性的对象,并且那些属性刚好有相同的名字和值。但他们也有一些显著的不同。numbers继承自Array.prototype,而number_object继承自Object.prototype.所以numbers可以有很多方法。同时,numbers还有一个length属性,而number_object则没有。

在大多数语言中,数组中元素的类型要求一致,但是在Javascript中可以包含任意混合类型的值,这一点值得注意~

2.长度

每个数组都有一个length属性,与大多数语言不同,JavaScript中数组是没有上界的。也就是说,可以随意扩充容量,只要当前length小于4 294 967 295即可。

如果重新设置length属性,特别是将其变小,则会导致所有下标大于等于新length的属性被删除。

numbers.length = 2;//numbers是['zero','one']

 

也可以用push附加一个新元素到该数组的尾部:

numbers.push('hi');   

3.删除

由于JavaScript的数组其实就是对象,所以delete运算符可以用来删除数组中的元素:

delete numbers[1];//numbers是['zero',undefined] 

也就是说,删除某个元素的数组,它并不会自动调整下标。

当然,用splice方法可以解决该问题,它会删除一些元素并将它们替换为其他的元素,因为被删除的属性后面每个属性必须被移除,并且以一个新的键值去重新插入,这种做法对于大型数组来说可能会效率不高。

4.枚举

用for就可以很好的实现了,至于for in,它无法保证属性的顺序。此外,它可能从原型链中得到意外的属性(我们可以用hasOwnProperty来排除)。

5.混淆的地方

在JavaScript中什么时候使用数组,什么时候使用对象呢~该书建议的规则就是:当属性名是小而且连续的整数时,你就应该使用数组吗,否则你就应该使用对象。

JavaScript本身就没有区别好数组和对象。(当然了,数组其实就是对象)

    var empty = [];
    alert(
typeof empty);//object

定义自己的函数来判断:

代码
var isArray = function(a){    
   
return a && 
   
typeof a === 'object' && 
   
typeof a.length === 'number' && 
   
typeof a.splice === 'function' && 
   
!(a.propertyIsEnumerable('length')); 
};

最后,我们判断的是length属性是否可以通过for in遍历出来,对于所有的数组来说,这会是false。这是该书所谓的最可靠的测试~

6.方法

JavaScript提供了一套作用于数组的方法,这些方法是存储在Array.prototype中的函数。当然,Array.prototype是可以被扩充的。

我们要扩充一个方法对数组进行计算:

代码
Function.prototype.method = function(name,func){    
   
this.prototype[name] = func;     
   
return this

Array.method(
'reduce',function(fn,value){     
   
for(var i=0,l=this.length;i<l;i++){        
   value 
= fn(this[i],value); 
   }     
   
return value; 
});

使用时:

代码
    var array = [4,8,15,18];
    
var add = function(a,b){
       
return a + b;    
    };
    
var mult = function(a,b){
       
return a * b;    
    };
    
var sum = array.reduce(add,0);//加起来
    var product = array.reduce(mult,1);//乘起来

 


这样看起来便和each有些类似了....

each方法,让元素依次传入,这里有一个漂亮的each方法(from 司徒正美 javascript Array对象

代码
   Array.prototype.each = function(fn){    
     
for (var i=0;i <this.length;i++
     
this[i].constructor==Array?         
     
this[i].each(fn):         
     fn.call(
this[i],i); 
  };  
 [
1,[2,[3,[4,[5,[6,[7,[8,[9,[0]]]]]]]]]].each(     
    
function(){         
       
return alert(this);     
    });

 

正如 司徒正美所说:上面这个比较强大,除了能深层遍历数组外,还能遍历类数组对象(如arguments,NodeList),对象的所有属性都会被fn方法进行调用。但是从设计模式来看,它承担职责太多了.each方法就应该是面向数组,如果是对象或类数组对象,我们应该将它们转化为数组,如JQuery的makeArray,mootools和Prototype的$A。

我在此将代码copy过来:

转换为对组对象:

代码
    var arrayize = function(iterable){ 
         
try{     
          
return Array.prototype.slice.call(iterable);   
       }
catch(e){     
          
var l = iterable.length || 0, array = new Array(l);     
          
while (l--) array[l] = iterable[l];     
          
return array;   
       } 
    }

 

实现纯数组的each

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

 

改成原型方法:

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

不过,如果浏览器支持javascript1.6的forEach方法,就用forEach:

    Array.prototype.each = function(func) { 
         
if(Array.prototype.forEach){        
                
this.forEach(func); 
              }
else{         
          each(func,
this);     
       } 
    };

 

当然,在此文中,作者还介绍了火狐实现each的一个方法,以及数组的其他方法,并且分析了Jquery中each实现的方式,在此就不多说了。

 


 

posted @ 2010-01-04 16:31  Tmac_  阅读(366)  评论(0)    收藏  举报