美文网首页前端让前端飞
《前端面试题》- JS基础 - 伪数组

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

作者: 张中华 | 来源:发表于2021-02-01 21:11 被阅读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()方法较为简单明了。

    相关文章

      网友评论

        本文标题:《前端面试题》- JS基础 - 伪数组

        本文链接:https://www.haomeiwen.com/subject/jbsstltx.html