一坑赡、什么是真數(shù)組(數(shù)組)
所謂真數(shù)組烙如,其實可以直接稱為:數(shù)組。
當一個對象具有以下特點時垮衷,可以稱為數(shù)組:
- 可以按照索引的方式厅翔,存儲多個數(shù)組
- 具有l(wèi)ength屬性乖坠,表示數(shù)組內(nèi)數(shù)據(jù)的長度(個數(shù))
- 對象的原型屬性
__proto__
搀突,指向Array
類,且可以使用Array
的原型對象prototype
身上的屬性和方法熊泵,如:push仰迁,pop等。如圖1:
二顽分、什么是偽數(shù)組
所謂偽數(shù)組徐许,當一個對象具有以下特點:
- 具有l(wèi)ength(長度)屬性;
- 可以使用索引對數(shù)據(jù)進行操作卒蘸;
- 但是不能使用數(shù)組的方法雌隅,如push,pop等缸沃。如圖2:
注意:
1.偽數(shù)組一般不會直接創(chuàng)建恰起,而是通過一些js操作得到,如:document.getElementsByName()
等趾牧;
2.因為偽數(shù)組具有長度和索引检盼,所以可以使用循環(huán)語句遍歷;
3.并不是能使用部分數(shù)組的方法翘单,就是稱為真數(shù)組吨枉;如圖3:
4.有些情況下,并不是將偽數(shù)組的原型__proto__
屬性設置為Array
的原型對象prototype
哄芜,就可以使用數(shù)組的方法貌亭。如圖4:
三、如何將偽數(shù)組轉成真數(shù)組
如果在一些情況下认臊,js給我們返回的是偽數(shù)組属提,但是我們想使用真數(shù)組的方法對之進行操作,那么此時就需要將偽數(shù)組轉成真數(shù)組之后,才能繼續(xù)使用冤议。
接下來我們根據(jù)偽數(shù)組和真數(shù)組的區(qū)別和特點斟薇,對偽數(shù)組做一下改造,將偽數(shù)組轉成真數(shù)組恕酸,以完成后續(xù)操作堪滨。
方法1:遍歷:創(chuàng)建一個空數(shù)組,循環(huán)遍歷偽數(shù)組蕊温,將遍歷出的數(shù)據(jù)逐一放在空數(shù)組中
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
var arr = []; // 先創(chuàng)建空數(shù)組
for(var i=0;i<ali.length;i++){ // 循環(huán)遍歷偽數(shù)組
arr[i] = ali[i]; // 取出偽數(shù)組的數(shù)據(jù)袱箱,逐個放在真數(shù)組中
}
arr.push("hello");
console.log(arr); // [li, li, li, li, "hello"]
方法2:使用slice方法:利用Array原型對象的slice方法,配合apply义矛,將slice中的this指向偽數(shù)組
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
var arr = Array.prototype.slice.apply(ali);
arr.push("hello");
console.log(arr); // [li, li, li, li, "hello"]
方法3:利用ES6提供的Array的from方法
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
var arr = Array.from(ali);
arr.push("hello");
console.log(arr); // [li, li, li, li, "hello"]
方法4:利用ES6提供的展開運算符(...)
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
var arr = [...ali];
arr.push("hello");
console.log(arr); // [li, li, li, li, "hello"]
方法5:利用原型的復制:將偽數(shù)組的proto復制為Array的prototype发笔。但是這種方法有局限性
- 手動創(chuàng)建具有索引和長度的對象,作為偽數(shù)組
var obj = {
0:"a",
1:"b",
2:"c",
length:3
}
console.log(obj); // {0: "a", 1: "b", 2: "c", length: 3}
// obj.push(); // TypeError: obj.push is not a function
obj.__proto__ = Array.prototype;
console.log(obj); // ["a", "b", "c"]
obj.push("hello");
console.log(obj); // ["a", "b", "c", "hello"]
- arguments也適用
function fn(){
var arg = arguments;
console.log(arg); // ["a", "b", ...]
// arg.push("hello"); // TypeError: arg.push is not a function
arg.__proto__ = Array.prototype;
arg.push("hello");
console.log(arg); // ["a", "b", "hello", ...]
}
fn("a","b");
- 選擇器返回的元素集合不適用凉翻,因為就算將元素集合的原型改成了數(shù)組原型(如圖5)了讨,但元素集合本身是只讀的,依然不能修改
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
ali.__proto__ = Array.prototype;
// ali.push("hello"); // Index property setter is not supported
但是不是意味著制轰,沒有修改到原數(shù)組的方法就可以使用呢(注意圖5前计,沒有l(wèi)ength屬性)
ali.forEach(val => {
console.log(val);
});
// 會發(fā)現(xiàn)瀏覽器沒執(zhí)行,原因是此時ali缺少length或length為0
console.log(ali.length); // 0
需要提前獲取ali的length垃杖,在修改原型之后再手動設置
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
var len = ali.length; // 獲取初始length
ali.__proto__ = Array.prototype;
ali.length = len; // 設置給修改原型之后的數(shù)組對象
// ali.push("hello"); // Index property setter is not supported
ali.forEach(val => {
console.log(val); // 遍歷打印數(shù)組中的值
});
console.log(ali.length); // 4
小提示:選擇器返回的元素數(shù)組男杈,使用復制原型方法,還需要手動設置length屬性调俘,且不能使用會改變原數(shù)組的方法伶棒。
以上。
關于偽數(shù)組轉真數(shù)組的方法或技巧彩库,后期繼續(xù)補充...
文中如果紕漏肤无,錯誤,不合理侧巨,描述不清晰舅锄,不準確等問題司忱,歡迎大家留言指正...