目录
前言
一、伪数组的概念
二、常见的伪数组
1、函数中存储所有实参的arguments对象
2、DOM提供的获取页面节点的方法
三、 数组与伪数组的区别
四、判断伪数组
五、伪数组转为真数组
前言
在学习数组方法后,对数组的理解更加深刻了。但是在javascript中存在伪数组的概念,那么伪数组是什么?与数组是什么关系?伪数组的“伪”体现在哪里呢?这篇文章就来学习一下伪数组吧!
一、伪数组的概念
伪数组是一种按照索引存储数据且具有 length
属性的对象。
具有以下特点:
1、可以使用索引对数据进行操作;
2、具有length(长度)属性;
3、但是不能使用数组的方法,如push,pop等数组方法
举个手写的伪数组例子:
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
二、常见的伪数组
1、函数中存储所有实参的arguments对象
function fn() {
(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 }
}
fn(1,2,3,4);
2、DOM提供的获取页面节点的方法
2.()获取到的NodeList 对象
var lis = ('li');
(lis);//NodeList(4) [li, li, li, li]
(function (value) {
(value);//lis内所有元素
})
注意:NodeList 对象是文档节点的集合,具有forEach方法,但不具有其他数组方法
2.2 ()、getElementsByTagName()、等等获取到的HTMLCollection对象
var lis = ('cat');
(lis);//HTMLCollection(4) [, , , ]
(function (value) {
(value);//Uncaught TypeError: is not a function
})
var lis = ('li');
(lis);//HTMLCollection(4) [, , , ]
(function (value) {
(value);//Uncaught TypeError: is not a function
})
注意:HTMLCollection对象是文档元素节点的集合,不具有任何数组方法
除此之外,还有很多常用的伪数组,就不一一列举。
三、 数组与伪数组的区别
1、伪数组与数组都属于对象,但是伪数组是基于Object构造函数创建的,数组是基于Array构造函数创建的。构造函数的方法写在其原型对象prototype开辟的内存内,基于构造函数创建的对象会拥有其方法。Object构造函数属于最*对象,因此根据原型链,伪数组只能拥有 的属性值,不能拥有 的属性值,因此不具有数组的方法。
var obj = {};// 拥有的属性值
var arr = [];//同时拥有和的属性值
2、伪数组的长度作为对象的一个属性,不会随索引属性的改变而改变。
四、判断伪数组
1、instanceof()
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr=[1,2,3,4];
(arrayLike instanceof Array);//false
(arr instanceof Array);//true
2、()
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr = [1, 2, 3, 4];
((arrayLike));//false
((arr));//true
3、《javascript权威指南》判断一个对象是否属于“类数组”
function isArrayLike(o) {
if (o && // o is not null, undefined, etc.
typeof o === 'object' && // o is an object
isFinite() && // is a finite number
>= 0 && // is non-negative
===() && // is an integer
< 4294967296) // < 2^32
return true; // Then o is array-like
else
return false; // Otherwise it is not
}
4、(),用于测试一个对象是否存在于另一个对象的原型链上。
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr = [1, 2, 3, 4];
((arrayLike)); // false
((arr)); // true
5、__proto__.constructor,判断对象隐式原型的构造函数
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr = [1, 2, 3, 4];
(arrayLike.__proto__.constructor);//ƒ Object() { [native code] }
(arr.__proto__.constructor);//ƒ Array() { [native code] }
6、()方法,传递要检查的对象作为第一个参数,称为 thisArg
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr = [1, 2, 3, 4];
((arrayLike)); //[object Object]
((arr)); //[object Array]
五、伪数组转为真数组
1、()
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr=(arrayLike);
((arr));//true
2、 slice()
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr = [].(arrayLike);
((arr));//true
3、concat()
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 3,
};
var arr = [].([], arrayLike);
((arr));//true
4、利用for循环遍历
var arrayLike = {
0: "x",
1: "y",
2: "z",
length: 5,
};
var arr = [];
for (var i = 0; i < ; i++) {
(arrayLike[i]);
}
(arr);// ['x', 'y', 'z']
5、扩展运算符
const el = [...('p')];
(el);// (3) [p, p, p]
注意:以上方法实现的原理都是通过拷贝伪数组,将其值添加到一个新数组中,完成真数组的转换,这些拷贝都是浅拷贝。如果伪数组中包含引用数据类型,新数组与伪数组对值的更改会互相影响。
6、封装函数,实现深拷贝伪数组
var arrayLike = {
0: "x",
1: "y",
2: "z",
3: [100, 200],
length: 4,
};
var arr = [];
// 封装函数
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
// 判断我们的属性值属于那种数据类型
// 1. 获取属性值 oldobj[k]
var item = oldobj[k];
// 2. 判断这个值是否是数组
if (item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k], item)//数组循环时,k为索引值,item为数组本身,newobj[0]='pink',newobj[1]=red;全部复制完后结束
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newobj[k] = {};
deepCopy(newobj[k], item)
} else {
// 4. 属于简单数据类型
newobj[k] = item;//第一次循环:k='id',item=1,将新对象属性值=旧对象属性值,同时新对象也创建了新属性
}
}
}
deepCopy(arr, arrayLike);
(arr);//['x', 'y', 'z', [100,200]]
arr[3][0] = 1000;
(arr);// ['x', 'y', 'z', [1000,200]]
(arrayLike);//{0: 'x', 1: 'y', 2: 'z', 3: [100,200], length: 4}未改变伪数组中的值
for (var i = 0; i < ; i++) {
(arr[i]);//x y z [1000,200]
}