数组是一段线性分配的内存,它通过整数去计算偏移并访问其中的元素。数组是很快的数据结构,但不幸的是,Javascript并没有像这种数组一样的数据结构。Javascript的数组实质是对象,它把数组的下标转换成字符串,用其作为属性,因此它明显比真正的数组慢,但它可以更方便地使用。
FF: Firefox, N: Netscape, IE: Internet Explorer
方法 | 描述 | FF | N | IE |
---|---|---|---|---|
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 |
方法 | 描述 | FF | N | IE |
---|---|---|---|---|
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.
}
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛