伪数组与真数组的转换
什么是伪数组以及转换为真数组的几种方法
问题
什么是伪数组(ArrayLike),如何转为真数组?
解答
什么是伪数组
伪数组是具有 length 属性和索引元素,但没有数组方法的对象。
// 常见的伪数组
const arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// DOM 集合是伪数组
const divs = document.querySelectorAll('div'); // NodeList
const inputs = document.getElementsByTagName('input'); // HTMLCollection
// 函数的 arguments 是伪数组
function test() {
console.log(arguments); // Arguments 对象
console.log(arguments.length); // 可以访问 length
// arguments.map() // 报错,没有数组方法
}
转换方法
1. Array.from()(推荐)
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
const arr = Array.from(arrayLike);
console.log(arr); // ['a', 'b', 'c']
console.log(Array.isArray(arr)); // true
// 可以同时进行映射
const arr2 = Array.from(arrayLike, item => item.toUpperCase());
console.log(arr2); // ['A', 'B', 'C']
2. 展开运算符
// 适用于可迭代对象(NodeList、arguments 等)
const divs = document.querySelectorAll('div');
const arr = [...divs];
function test() {
const args = [...arguments];
console.log(Array.isArray(args)); // true
}
// 注意:普通对象不可迭代,会报错
const obj = { 0: 'a', 1: 'b', length: 2 };
// [...obj] // TypeError: obj is not iterable
3. Array.prototype.slice.call()
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
const arr = Array.prototype.slice.call(arrayLike);
// 或简写
const arr2 = [].slice.call(arrayLike);
console.log(arr); // ['a', 'b', 'c']
4. Array.prototype.concat.apply()
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
const arr = Array.prototype.concat.apply([], arrayLike);
console.log(arr); // ['a', 'b', 'c']
判断是否为伪数组
function isArrayLike(obj) {
// 排除 null、undefined 和 window
if (obj == null || obj === window) return false;
// 排除函数(函数也有 length 属性)
if (typeof obj === 'function') return false;
const length = obj.length;
// length 必须是非负整数
return typeof length === 'number'
&& length >= 0
&& Number.isInteger(length);
}
console.log(isArrayLike({ 0: 'a', length: 1 })); // true
console.log(isArrayLike([1, 2, 3])); // true
console.log(isArrayLike('hello')); // true(字符串也是伪数组)
console.log(isArrayLike({ name: 'test' })); // false
关键点
- 伪数组有
length和索引,但没有push、map等数组方法 Array.from()是最通用的转换方法,支持映射函数- 展开运算符
[...]只能用于可迭代对象 arguments、NodeList、HTMLCollection是常见的伪数组- 字符串也是伪数组,可以用索引访问字符
目录