• 如何将类数组转化为数组


    首先,什么是类数组(Array Like)?

    一个简单的定义,如果一个对象有 length 属性值,则它就是类数组

    那常见的类数组有哪些呢?

    这在 DOM 中甚为常见,如各种元素检索 API 返回的都是类数组,如 document.getElementsByTagNamedocument.querySelectorAll 等等。除了 DOM API 中,常见的 function 中的 arguments 也是类数组

    那如何把类数组转化为数组呢?这是类数组操作时一个典型的场景,也是一个典型的面试题

    以下我们将以 { length: 3 } 来指代类数组,来作为演示

    节选自 日文 【Q168】在 js 中如何把类数组转化为数组。另外这里有更多的 前端面试题,欢迎交流

    ES6+

    ES6 中有现成的 API:Array.from,极为简单

    // [undefined, undefined, undefined]
    Array.from({ length: 3 })
    

    除了 Array.from 还有更简单的运算符 ... 扩展运算符,不过它只能作用于 iterable 对象,即拥有 Symbol(Symbol.iterator) 属性值

    拥有 Symbol(Symbol.iterator) 属性值,意味着可以使用 for of 来循环迭代

    // 适用于 iterable 对象
    [...document.querySelectorAll('div')]
    

    但是严格意义上来说,它不能把类数组转化为数组,如 { length: 3 }。它将会抛出异常

    // Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
    [...{length: 3}]
    

    ES5

    在此之前,我们先不使用 { length: 3 },使用以下数据来代表类数组

    const arrayLike = {
      0: 3,
      1: 4,
      2: 5,
      length: 3
    }
    

    ES5 中可以借用 Array API 通过 call/apply 改变 this 或者 arguments 来完成转化。

    最常见的转换是 Array.prototype.slice

    Array.prototype.slice.call(arrayLike)
    

    当然由于借用 Array API,一切以数组为输入,并以数组为输出的 API 都可以来做数组转换,如

    • Array (借用 arguments)
    • Array.prototype.concat (借用 arguments)
    • Array.prototype.slice (借用 this)
    • Array.prototype.map (借用 this)
    • Array.prototype.filter (借用 this)
    Array.apply(null, arrayLike)
    Array.prototype.concat.apply([], arrayLike)
    Array.prototype.slice.call(arrayLike)
    Array.prototype.map.call(arrayLike, x => x)
    Array.prototype.filter.call(arrayLike, x => 1)
    

    此时一切正常,但是忘了一个特例,稀疏数组。在此之前,先做一个题,以下代码输出多少

    // 该代码输出多少
    Array(100).map(x => 1)
    

    参考 Array(100).map(x => 1) 结果是多少

    稀疏数组 (sparse array)

    使用 Array(n) 将会创建一个稀疏数组,为了节省空间,稀疏数组内含非真实元素,在控制台上将以 empty 显示,如下所示

    [,,,]Array(3) 都将返回稀疏数组

    > [,,,]
    [empty × 3]
    > Array(3)
    [empty × 3]
    

    当类数组为 { length: 3 } 时,一切将类数组做为 this 的方法将都返回稀疏数组,而将类数组做为 arguments 的方法将都返回密集数组

    总结

    由上总结,把类数组转化成数组最靠谱的方式是以下三个

    Array.from(arrayLike)
    Array.apply(null, arrayLike)
    Array.prototype.concat.apply([], arrayLike)
    

    以下几种方法需要考虑稀疏数组的转化

    Array.prototype.filter.call(divs, x => 1)
    Array.prototype.map.call(arrayLike, x => x)
    Array.prototype.filter.call(arrayLike, x => 1)
    

    以下方法要注意是否是 iterable object

    [...arrayLike]
    
  • 相关阅读:
    Flink Application Development DataStream API Execution Mode (Batch/Streaming)- Flink应用程序开发DataStream API执行模式(批/流)
    Flink Application Development DataStream API Overview
    Flink Concept Stateful Stream Processing -Flink概念有状态流处理
    Hdfs原理
    Leetcode 763 划分字母区间
    406. 根据身高重建队列
    贝叶斯统计概要(待修改)
    蒙特卡罗方法
    马尔科夫链蒙特卡罗方法(MCMC)
    Leetcode452. 用最小的箭引爆气球
  • 原文地址:https://www.cnblogs.com/xianwang/p/12189635.html
Copyright © 2020-2023  润新知