簡單來講,和數組相似,擁有
length
屬性,能夠經過索引來訪問或設置裏面的元素,可是不能使用數組的方法。javascript
看個例子:html
arr[0];
// => "dazhi"
複製代碼
這裏的arr
必定是一個數組嗎?不必定,也多是一個對象。前端
let arr = {
0: 'dazhi'
}
console.log(arr[0]); // dazhi
複製代碼
再來看個例子:java
let arr = ['name', 'age', 'job'];
// 建立一個類數組對象
let arrLike = {
0: 'name',
1: 'age',
2: 'job',
length: 3
}
複製代碼
注意:這邊arrLike必須加上length
屬性,否則它就是一個普通對象而已。git
爲何叫作類數組對象呢?咱們從讀寫、獲取長度、遍歷這三個方面來看看這兩個對象。github
console.log(arr[0]); // name
console.log(arrLike[0]); // name
arr[0] = 'new name';
arrLike[0] = 'new name';
console.log(arr[0]); // new name
console.log(arrLike[0]); // new name
複製代碼
console.log(arr.length); // 3
console.log(arrLike.length); // 3
複製代碼
for (let i = 0;i < arr.length; i++){
console.log(arr[i]);
}
// name
// age
// job
for (let i = 0;i < arrLike.length; i++){
console.log(arrLike[i]);
}
// name
// age
// job
複製代碼
有沒有很像?當咱們使用使用數組的方法呢?繼續往下看:數組
arr.push('gender');
arrLike.push('gender'); // 報錯
複製代碼
原形畢露了,終歸是類數組。app
那若是類數組
就想用數組的方法呢?能夠把類數組
轉換爲數組。函數
var arrLike2 = Array.prototype.slice.call(arrLike);
arrLike2.push('gender');
console.log(arrLike2[3]); // gender
複製代碼
var arrLike3 = Array.from(arrLike);
arrLike3.push('gender');
console.log(arrLike3[3]); // gender
複製代碼
var arrLike4 = Array.prototype.splice.call(arrLike, 0);
arrLike4.push('gender');
console.log(arrLike4[3]); // gender
複製代碼
若是length
值和實際元素不相等呢?學習
let arrLike = {
0: 'name',
1: 'age',
length: 3
}
console.log(Array.from(arrLike)); // ["name", "age", undefined]
複製代碼
能夠看到,若是length
值大於實際元素的數量,不足的將用undefined
填充。
若是反過來呢?
let arrLike = {
0: 'name',
1: 'age',
length: 1
}
console.log(Array.from(arrLike)); // ["name"]
複製代碼
最終只保留了一個元素。可見,length
值是決定最終生成數組的長度的,多餘的去掉,不足的用undefined
填充。
那若是咱們索引不從0和1開始,能夠嗎?
let arrLike = {
2: 'name',
3: 'age',
length: 2
}
console.log(Array.from(arrLike)); // [undefined, undefined]
複製代碼
可見,0和1是有用的,會影響到最終的填充索引。
說了這麼多,類數組能用來作什麼?
還記得arguments
對象嗎?它就是一個類數組對象。咱們看下MDN
上對其的描述:
arguments
對象是全部(非箭頭)函數中均可用的局部變量。你可使用arguments
對象在函數中引用函數的參數。arguments
對象不是一個Array
。它相似於Array
,但除了length屬性和索引元素以外沒有任何Array
屬性。例如,它沒有pop
方法。但它能夠被轉換爲一個真正的Array
。
MDN地址:developer.mozilla.org/zh-CN/docs/…
看個例子:
function foo(a, b, c) {
console.log(arguments);
}
foo(1, 2, 3);
複製代碼
控制檯看下打印結果:
咱們能夠經過arguments
對象在函數內部引用傳遞進來的參數:
function foo(a, b, c) {
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
foo(1, 2, 3);
// 1
// 2
// 3
複製代碼
arguments
的length
屬性表明的是實參的個數,由於咱們調用函數的時候,有時候並非全部參數都須要傳入,看下面的代碼:
function foo(a, b, c) {
console.log('實參的個數:' + arguments.length); // 1
}
foo(1);
console.log('形參的個數爲:' + foo.length); // 3
複製代碼
function foo(a, b, c, d) {
// "use strict";
console.log(a, arguments[0]); // 1 1
// 改變形參
a = 11;
console.log(a, arguments[0]); // 11 11
// 改變arguments
arguments[1] = 22;
console.log(b, arguments[1]); // 22 22
// 未傳入的參數
console.log(c); // undefined
c = 3;
console.log(c, arguments[2]); // 3 undefined
arguments[3] = 4;
console.log(d, arguments[3]); // undefined 4
}
foo(1, 2);
複製代碼
總結:
arguments
的值會共享,沒有傳入的參數,不會共享arguments
的值都不會共享將參數從一個函數傳遞到另外一個函數。
function foo() {
bar.apply(this, arguments);
}
function bar(a, b, c) {
console.log(a, b, c);
}
foo(1, 2, 3);
// 1 2 3
複製代碼
arguments
除了能夠用上面的幾個轉爲數組的方法,還可使用...
展開運算符。
function bar(a, b) {
// 用...把argumens轉爲數組
console.log([...arguments]); // [1, 2]
}
bar(1, 2);
複製代碼
可是若是應用到普通的類數組對象呢?
let arrLike5 = {
a: 1,
b: 2,
length: 2
}
console.log([...arrLike5]); // 報錯 Uncaught TypeError: arrLike5 is not iterable
複製代碼
報錯的意思是:arrLike5不是可迭代的,也就證明了arguments
除了是類數組對象,仍是一個可迭代對象,而咱們自定義的對象並不具有可迭代功能,因此不能使用展開運算符。
由於咱們自定義的類數組對象不具有可迭代功能,因此也沒辦法使用for...of
來遍歷:
let arrLike = {
0: 'name',
1: 'age',
2: 'job',
length: 3
}
for (let arrItem of arrLike) {
console.log(arrItem);
}
// 一樣會報錯 Uncaught TypeError: arrLike is not iterable
複製代碼
那麼forEach
和for...in
呢?
forEach
是數組的方法,天然也沒辦法使用。
來看下for...in
:
let arrLike = {
0: 'name',
1: 'age',
2: 'job',
length: 3
}
for (let index in arrLike) {
console.log(index);
}
// 0
// 1
// 2
// length
複製代碼
for...in
是遍歷對象的可枚舉屬性,會把length
也遍歷出來。
因此只有for循環能夠正確遍歷類數組對象。
另外,arguments
的應用其實還有不少,這裏就不繼續展開了,你們有興趣能夠本身再去找資料學習一下,好比:
咱們在頁面上隨便寫幾個p
標籤:
<p></p>
<p></p>
<p></p>
複製代碼
而後用document.getElementsByTagName()
獲取:
var ps = document.getElementsByTagName('p');
console.log(ps);
複製代碼
能夠看到,裏面也有length
屬性,可是它並非一個數組,咱們能夠來檢測一下:
// 類數組對象不能使用數組的方法
ps.push('a'); // 報錯:Uncaught TypeError: ps.push is not a function
console.log(Object.prototype.toString.call(ps)); // [object HTMLCollection]
console.log(Object.prototype.toString.call([])); // [object Array]
複製代碼
好了,本文就先到這裏了。
感謝您的閱讀,但願對你有所幫助。因爲本人水平有限,若是文中有描述不當的地方,煩請指正,很是感謝。
歡迎你們關注個人公衆號前端幫幫忙
,一塊兒交流學習,共同進步!
參考: