數組定義:簡而言之就是一組有序的數據集合,其索引爲從0開始且自然增長的整數,其元素值可以是任何js數據!並且包含一個名爲length的屬性,該屬性表示數組元素的個數!
看着上面的定義,我們很容易就能大概知道數組是什麼樣的東西,下面我們來看個簡單的例子:
1
2
3
4
5
|
var array
= [1,2,3]; console.log(array[0]) //1 console.log(array[1]) //2 console.log(array[2]) //3 console.log(array[ 'length' ]) //3 |
從上面的例子我們可以看到,在聲明數組時,我們只是顯式的聲明瞭數組元素的值,並沒有顯式的給這些值定義索引和length屬性,但是在數組定義好後我們發現就可以直接使用數組的索引值來操作數組的元素了,從這不難看出,數組元素的索引和length屬性是在數組定義時根據數組元素語言自動就幫你定義好了!而且很容易就能看出來,索引值是從0開始並且自然遞增的!
對象定義:js中對象類型爲一組無序的由鍵->值組成的數據集合,其元素的鍵名和值都可以自定義!
我們來看一個例子:
1
2
3
4
|
var object
= { 'a' :
1, 'b' :
2} console.log(object[ 'a' ]) //1 console.log(object[ 'b' ]) //2 console.log(object[ 'length' ]) //undefined |
從上面的例子簡單來看,對象自身所擁有的(不包括繼承來的)任何屬性都是有用戶自定義的!
數組與對象:
從上面的定義和例子上來看,不知道大家有沒有發現,數組和對象在某些地方或時候其實是很相像的!
我們先看看他們相同的部分,首先我們可以把數組的索引值看成的元素的鍵名,元素看成是值,那麼數組是不是也變成了鍵->值構成的了!
我們在來看看他們不一樣的地方,數組的所以值始終的從0開始遞增的數字,對象的屬性值可以是任何自定義的字符串,並且數組包含一個length屬性,而對象自身所擁有的(不包括繼承來的)任何屬性都是有用戶自定義的!也就是說我們,我們可以給顯式的給對象定義length屬性!
1
2
3
4
|
var arr
= [1,2,3]; var obj
= {0: 1, 1: 2, 2: 3, length: 3}; console.log(arr[0],
obj[0]) //1,
1 console.log(arr[ 'length' ],
obj[ 'length' ]) //1,
1 |
通過對比,我們發現完全可以使用對象來模擬數組,只要我們定義的對象的每個元素的鍵名都使用數字並且讓其保持遞增,且動態的定義一個length屬性來表示元素個數,那麼從效果上來說,基本就個數組相同了!這就是我們要說的:
類數組對象:只包含使用從零開始,且自然遞增的整數做鍵名,並且定義了length表示元素個數的對象,我們就認爲他是類數組對象!
類數組對象不僅是效果上跟數組相似,並且在某些操作上也相同:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//定義數組和類數組對象 var arr
= [1,2,3]; var obj
= {0: 1, 1: 2, 2: 3, length: 3}; //元素讀寫操作 console.log(arr[0],
obj[0]) //1,
1 console.log(arr[ 'length' ],
obj[ 'length' ]) //1,
1 arr[0]
= 9; obj[0]
= 9; //遍歷 for ( var i
= 0, len = arr.length; i < len; i++) { arr[i].... } for ( var i
= 0, len = obj.length; i < len; i++) { obj[i].... } |
我們看到,不僅在讀寫等操作上類數組對象和數組相似,並且在遍歷元素上都可以使用for循環進行遍歷!
類數組Array-like定義:
- 擁有length屬性,其它屬性(索引)爲非負整數(對象中的索引會被當做字符串來處理,這裏你可以當做是個非負整數串來理解)
- 不具有數組所具有的方法
ps:這是我參考的定義,實際上,只要有length
屬性,且它的屬性值爲number
類型就行了。請圍觀評論。
類數組示例:
var a = {'1':'gg','2':'love','4':'meimei',length:5};
Array.prototype.join.call(a,'+');//'+gg+love++meimei'
非類數組示例:
var c = {'1':2};
沒有length
屬性,所以就不是類數組。
javascript中常見的類數組有arguments
對象和DOM方法的返回結果。
比如 document.getElementsByTagName()
。
類數組判斷
《javascript權威指南》上給出了代碼用來判斷一個對象是否屬於“類數組”。如下:
// Determine if o is an array-like object.
// Strings and functions have numeric length properties, but are
// excluded by the typeof test. In client-side JavaScript, DOM text
// nodes have a numeric length property, and may need to be excluded
// with an additional o.nodeType != 3 test.
function isArrayLike(o) {
if (o && // o is not null, undefined, etc.
typeof o === 'object' && // o is an object
isFinite(o.length) && // o.length is a finite number
o.length >= 0 && // o.length is non-negative
o.length===Math.floor(o.length) && // o.length is an integer
o.length < 4294967296) // o.length < 2^32
return true; // Then o is array-like
else
return false; // Otherwise it is not
}
類數組表現
之所以成爲“類數組”,就是因爲和“數組”類似。不能直接使用數組方法,但你可以像使用數組那樣,使用類數組。
var a = {'0':'a', '1':'b', '2':'c', length:3}; // An array-like object
Array.prototype.join.call(a, '+''); // => 'a+b+c'
Array.prototype.slice.call(a, 0); // => ['a','b','c']: true array copy
Array.prototype.map.call(a, function(x) {
return x.toUpperCase();
}); // => ['A','B','C']:
類數組對象轉化爲數組
有時候處理類數組對象的最好方法是將其轉化爲數組。
Array.prototype.slice.call(arguments)
然後就可以直接使用數組方法啦。
var a = {'0':1,'1':2,'2':3,length:3};
var arr = Array.prototype.slice.call(a);//arr=[1,2,3]
對於IE9以前的版本(DOM實現基於COM),我們可以使用makeArray
來實現。
// 僞數組轉化成數組
var makeArray = function(obj) {
if (!obj || obj.length === 0) {
return [];
}
// 非僞類對象,直接返回最好
if (!obj.length) {
return obj;
}
// 針對IE8以前 DOM的COM實現
try {
return [].slice.call(obj);
} catch (e) {
var i = 0,
j = obj.length,
res = [];
for (; i < j; i++) {
res.push(obj[i]);
}
return res;
}
};