前端让前端飞

《前端面试题》- JS基础 - 伪数组

2021-02-01  本文已影响0人  张中华

第一次听说伪数组这个概念,听到的时候还以为是说CSS的伪类呢,网上一查,这东西原来还是个很常见的家伙。

何为伪数组

伪数组有两个特点:

  1. 具有length属性,其他属性(索引)为非负整数
  2. 但是却不具备数组的方法
    也就是看起来像是数组,然而并不是...

举个例子看看

  1. 函数内部的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);
test result
  1. DOM列表


  2. JQuery选择得出的列表: $('div')
    随意找一个使用jq的网站,例如:https://www.jq22.com/

如何判断真伪数组

  1. 使用instanceof 方法
  2. 使用Array.isArray()方法: 未必准确,见下文, 使用伪数组.__proto__ = Array.prototype;转换后不可用。
  3. 伪数组.constructor === Array; 适用于带constructor的场景
  4. 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);

如何把伪数组转换成数组

  1. Array.prototype.slice.call(); / Array.prototype.slice.apply();
  2. 原型继承: 伪数组.__proto__ = Array.prototype;arguments 无影响正常使用
  3. 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);

总结

  1. 在使用判断是否为数组时,如果无法知道数组是否可能是使用“原型继承”的方法转换得到的,就不要使用Array.isArray()方法判断对象是否为数组的方法。
  2. 在写转换方法时,由于原型继承: 伪数组.__proto__ = Array.prototype;可能存在判断失误,尽量使用Array.prototype.slice.call(); / Array.prototype.slice.apply();如果可以使用ES6,使用Array.from()方法较为简单明了。
上一篇下一篇

猜你喜欢

热点阅读