JavaScript中Array
数组是一段线性的数据结构,这种数据结构一般来说是很快的,但不幸的是,JavaScript中并没有这种数据结构。
然后,JavaScript提供了一种类似数组(array-like)的结构。它把数组的下标转变成字符串,用其作为属性。正因为如此,它会比真正的数组要慢,但是并不影响其使用。
1.数组字面量
数组字面量提供了一种非常方便的创建新数组的表示法。
代码
var numbers = [
'zero','one','two',
'three','four'
]
empty[1] //undefined
numbers[1] //'one'
empty.length //0
numbers.length //5
当然,与其他语言类似,JavaScript中数组的"下标"是从0开始的。另外,也可以有另外一种方式创建数组:
在实际中,普遍会采用第一种创建数组的方式,因为第一种方式更为简洁,速度也更快。
与该数组字面量对应的是一个对象字面量:
'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的属性被删除。
也可以用push附加一个新元素到该数组的尾部:
3.删除
由于JavaScript的数组其实就是对象,所以delete运算符可以用来删除数组中的元素:
也就是说,删除某个元素的数组,它并不会自动调整下标。
当然,用splice方法可以解决该问题,它会删除一些元素并将它们替换为其他的元素,因为被删除的属性后面每个属性必须被移除,并且以一个新的键值去重新插入,这种做法对于大型数组来说可能会效率不高。
4.枚举
用for就可以很好的实现了,至于for in,它无法保证属性的顺序。此外,它可能从原型链中得到意外的属性(我们可以用hasOwnProperty来排除)。
5.混淆的地方
在JavaScript中什么时候使用数组,什么时候使用对象呢~该书建议的规则就是:当属性名是小而且连续的整数时,你就应该使用数组吗,否则你就应该使用对象。
JavaScript本身就没有区别好数组和对象。(当然了,数组其实就是对象)
alert(typeof empty);//object
定义自己的函数来判断:
代码
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是可以被扩充的。
我们要扩充一个方法对数组进行计算:
代码
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 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对象 )
代码
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过来:
转换为对组对象:
代码
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
for (var i=0,l = array.length; i<l; ++i) {
func(array[i])
}
}
改成原型方法:
不过,如果浏览器支持javascript1.6的forEach方法,就用forEach:
if(Array.prototype.forEach){
this.forEach(func);
}else{
each(func,this);
}
};
当然,在此文中,作者还介绍了火狐实现each的一个方法,以及数组的其他方法,并且分析了Jquery中each实现的方式,在此就不多说了。

浙公网安备 33010602011771号