一、什么是真数组?
当一个对象具有以下特点时,可以称为数组:
- 可以按照索引的方式,存储多个数组
- 具有length属性,表示数组内数据的长度(个数)
- 对象的原型属性__proto__,指向Array类,且可以使用Array的原型对象prototype身上的属性和方法,如:push,pop,shift,unshift等。
二、什么是伪数组?
- 具有length(长度)属性;
- 可以使用索引对数据进行操作;
- 但是不能使用数组的方法,如push,pop等;
- 因为伪数组具有长度和索引,所以可以使用循环语句遍历;
- 就算给伪数组挂一个push方法,对应Array.prototype.push,但其constructor依然指向Object而不是Array,还是伪数组)
三、注意区别
- 伪数组一般不会直接创建,而是通过一些js操作得到,如:
document.getElementsByClassName()等; - 并不是能使用部分数组的方法,就是称为真数组;
- 有些情况下,并不是将伪数组的原型
__proto__属性设置为Array的原型对象prototype,就可以使用数组的方法
四、将伪数组转成真数组
如果在一些情况下,js给我们返回的是伪数组,但是我们想使用真数组的方法对之进行操作,那么此时就需要将伪数组转成真数组之后,才能继续使用。
接下来我们根据伪数组和真数组的区别和特点,对伪数组做一下改造,将伪数组转成真数组,以完成后续操作。
方法1:利用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"]
方法2:遍历:创建一个空数组,循环遍历伪数组,将遍历出的数据逐一放在空数组中
var ali = document.getElementsByTagName('li');
console.log(ali); // [li, li, li, li]
// ali.push("hello"); // TypeError: ali.push is not a function
var arr = []; // 先创建空数组
for(var i=0;i<ali.length;i++){ // 循环遍历伪数组
arr[i] = ali[i]; // 取出伪数组的数据,逐个放在真数组中
}
arr.push("hello");
console.log(arr); // [li, li, li, li, "hello"]
方法3:利用原型的复制:将伪数组的__proto__复制为Array的prototype。但是这种方法有局限性
手动创建具有索引和长度的对象,作为伪数组
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"]