第一次听说伪数组这个概念,听到的时候还以为是说CSS的伪类呢,网上一查,这东西原来还是个很常见的家伙。
何为伪数组
伪数组有两个特点:
- 具有length属性,其他属性(索引)为非负整数
- 但是却不具备数组的方法
也就是看起来像是数组,然而并不是…
举个例子看看
- 函数内部的arguments
function testArguments(a, b, c) {console.log(`arguments is array: ${Array.isArray(arguments)}`);console.log(arguments[0]);console.log(arguments[1]);console.log(arguments[2]);
}
testArguments(1,2,3);
2. DOM列表
- JQuery选择得出的列表: $(‘div’)
随意找一个使用jq的网站,例如:https://www.jq22.com/
如何判断真伪数组
- 使用instanceof 方法
- 使用Array.isArray()方法: 未必准确,见下文, 使用
伪数组.__proto__ = Array.prototype;
转换后不可用。 - 伪数组.constructor === Array; 适用于带constructor的场景
- Object.prototype.toString.call(arr) === ‘[object Array]’
尝试一下:
function testArguments(a, b, c) {console.log(`arguments is array: ${Array.isArray(arguments)}`);console.log(`arguments is array: ${arguments instanceof Array}`);console.log(`arguments is object: ${arguments instanceof Object}`);const newArguments = Array.prototype.slice.call(arguments);console.log(`newArguments is array: ${Array.isArray(newArguments)}`);console.log(`newArguments is array: ${newArguments instanceof Array}`);console.log(`newArguments is object: ${newArguments instanceof Object}`);
}testArguments(1,2,3);
如何把伪数组转换成数组
Array.prototype.slice.call(); / Array.prototype.slice.apply();
- 原型继承:
伪数组.__proto__ = Array.prototype;
arguments 无影响正常使用 - ES6中数组的新方法 from()
方法一: Array.prototype.slice.call(); / Array.prototype.slice.apply();
function testArguments(a, b, c) {console.log(`arguments is array: ${Array.isArray(arguments)}`);console.log(arguments[0]);console.log(arguments[1]);console.log(arguments[2]);const newArguments = Array.prototype.slice.call(arguments);console.log(`newArguments is array: ${Array.isArray(newArguments)}`);console.log(newArguments[0]);console.log(newArguments[1]);console.log(newArguments[2]);
}
testArguments(1,2,3);
方法二: 原型继承: 伪数组.__proto__ = Array.prototype;
arguments 无影响正常使用
使用该方法进行转换时,Array.isArray()方法不可用来进行判断。
方法三: ES6中数组的新方法 from()
尝试一下:
function testArguments(a, b, c) {console.log(`arguments is array: ${Array.isArray(arguments)}`);console.log(`arguments is array: ${arguments instanceof Array}`);const newArguments = Array.from(arguments);console.log(`newArguments is array: ${Array.isArray(newArguments)}`);console.log(`newArguments is array: ${newArguments instanceof Array}`);
}
testArguments(1,2,3);
总结
- 在使用判断是否为数组时,如果无法知道数组是否可能是使用“原型继承”的方法转换得到的,就不要使用Array.isArray()方法判断对象是否为数组的方法。
- 在写转换方法时,由于原型继承:
伪数组.__proto__ = Array.prototype;
可能存在判断失误,尽量使用Array.prototype.slice.call(); / Array.prototype.slice.apply();如果可以使用ES6,使用Array.from()方法较为简单明了。