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