0

0

js 怎样用from将类数组对象转为真数组

畫卷琴夢

畫卷琴夢

发布时间:2025-08-07 08:33:01

|

633人浏览过

|

来源于php中文网

原创

array.from() 可将类数组或可迭代对象转换为真数组,1. 它通过识别对象的 length 属性和索引或 symbol.iterator 接口实现转换;2. 常用于处理 nodelist、arguments 或自定义类数组对象;3. 支持第二个参数映射函数,实现转换时同步处理元素;4. 与 [...spread] 相比能处理不可迭代的类数组,与 slice.call 相比语法更清晰且支持映射;5. 可生成指定长度数组、转换 set/map、结合 thisarg 使用;6. 注意仅适用于类数组或可迭代对象,对普通对象返回空数组,且为浅拷贝,需警惕引用共享问题,同时不可与 array.of() 混淆,后者用于创建新数组而非转换结构。

js 怎样用from将类数组对象转为真数组

Array.from()
是 JavaScript 中一个非常实用的方法,它能将类数组对象或可迭代对象(Iterable)高效地转换成一个真正的数组实例。简单来说,当你拿到一个看起来像数组但又不能直接调用数组方法(比如
map
filter
)的对象时,
Array.from()
就是你的救星,它会创建一个全新的、浅拷贝的数组。

解决方案

要用

Array.from()
将类数组对象转为真数组,核心在于理解它如何识别“类数组”或“可迭代”对象。一个对象只要具备
length
属性和可访问的索引(比如
obj[0]
,
obj[1]
),或者它是一个可迭代对象(实现了
Symbol.iterator
接口),
Array.from()
就能对其进行操作。

最常见的场景就是处理 DOM

NodeList
、函数内部的
arguments
对象,或者你自己构造的带有
length
属性的对象。

基本用法示例:

  1. 转换

    NodeList
    (DOM元素集合): 当你通过
    document.querySelectorAll()
    获取到一组元素时,得到的是一个
    NodeList
    ,它不是一个真正的数组。

    const divs = document.querySelectorAll('div'); // 这是一个NodeList
    const divArray = Array.from(divs); // 现在divArray就是一个真数组了
    
    // 可以在divArray上使用所有数组方法
    divArray.forEach(div => console.log(div.textContent));
  2. 转换

    arguments
    对象: 在函数内部,
    arguments
    是一个类数组对象,包含了函数调用时传入的所有参数。

    function sumAll() {
        // arguments是一个类数组对象
        const argsArray = Array.from(arguments);
        return argsArray.reduce((acc, val) => acc + val, 0);
    }
    
    console.log(sumAll(1, 2, 3, 4)); // 输出 10
  3. 转换自定义的类数组对象: 只要你的对象有

    length
    属性和索引元素,
    Array.from()
    就能处理。

    const myCollection = {
        0: 'apple',
        1: 'banana',
        2: 'orange',
        length: 3
    };
    
    const fruits = Array.from(myCollection); // ['apple', 'banana', 'orange']
    console.log(fruits instanceof Array); // true
  4. 结合映射函数进行转换和处理:

    Array.from()
    的第二个参数是一个映射函数(
    mapFn
    ),这让它在转换的同时还能对每个元素进行处理。这功能非常强大,省去了先转换再
    map
    的步骤。

    const numbers = Array.from({ length: 5 }, (_, i) => i * 2);
    // 生成 [0, 2, 4, 6, 8]
    // 第一个参数是 { length: 5 },一个简单的类数组对象
    // 第二个参数是映射函数,_ 表示当前元素(这里是 undefined),i 是索引
    
    const stringLengths = Array.from('hello', char => char.charCodeAt(0));
    // 将字符串(可迭代)转换为字符的ASCII码数组 [104, 101, 108, 108, 111]

为什么我们需要将类数组对象转换为真数组?

这问题问得好,因为这确实是 JavaScript 开发中一个很常见的痛点。我们之所以执着于把类数组对象变成“真”数组,最核心的原因就是方法缺失。你想想,当你拿到一个

NodeList
或者
arguments
对象时,你没法直接调用
map
filter
reduce
甚至是
forEach
(虽然
NodeList
arguments
有时会有
forEach
,但那不是
Array.prototype.forEach
,行为上可能存在细微差异或兼容性问题),更别提
sort
slice
splice
这些功能强大的数组方法了。

这就好像你买了一辆车,它看起来像车,开起来也像车,但它没有方向盘、没有刹车、没有油门,你只能看着它。类数组对象就是这样,它们有

length
属性,有索引,让你觉得它们是数组,但它们没有继承
Array.prototype
上的那些好用方法。

所以,转换为真数组,就是为了解锁这些原生数组方法,让数据处理变得更灵活、更符合直觉。一旦它们变成了真数组,你就可以用链式调用 (

.map(...).filter(...).reduce(...)
) 来进行复杂的数据转换和聚合,代码也会变得更简洁、更具表达力。这在我看来,是提高开发效率和代码可读性的关键一步。

Array.from() 与其他转换方法的区别在哪里?

Array.from()
出现之前,我们处理类数组对象主要有两种方式,现在有了
Array.from()
和 ES6 的展开运算符(Spread Syntax),选择就更多了。它们各有特点,理解这些差异能帮助你选择最适合的工具

  1. [].slice.call(arrayLikeObject)
    (经典方法): 这是 ES6 之前最常用的转换技巧。它的原理是“借用”
    Array.prototype.slice
    方法。
    slice
    方法在没有参数时,会返回原数组的一个浅拷贝。通过
    call
    方法,我们将
    this
    上下文指向类数组对象,从而让
    slice
    像处理数组一样处理它。

    const divs = document.querySelectorAll('div');
    const divArrayOld = [].slice.call(divs);

    区别:

    • 简洁性:
      Array.from()
      更直观,意图更明确。
      [].slice.call()
      看起来有点像“黑魔法”,需要理解
      call
      的作用和
      slice
      的行为。
    • 功能:
      Array.from()
      可以直接传入映射函数,实现转换和映射一步到位。
      slice.call
      只能做转换,如果需要映射,还得再跟一个
      map
      方法。
    • 兼容性:
      Array.from()
      是 ES6 新增的,IE 浏览器需要 Polyfill。
      slice.call
      兼容性更好。
    • 可迭代对象:
      slice.call
      只能处理类数组对象(有
      length
      和索引),而
      Array.from()
      还能处理任何可迭代对象(如
      Set
      map
      、字符串),这是它一个非常大的优势。
  2. 展开运算符 (

    ...
    Spread Syntax): 如果类数组对象是可迭代的(比如
    NodeList
    、字符串、
    Set
    map
    ),你也可以使用展开运算符将其转换为数组。

    const divs = document.querySelectorAll('div');
    const divArraySpread = [...divs];
    
    const mySet = new Set([1, 2, 3]);
    const setArray = [...mySet]; // [1, 2, 3]

    区别:

    • 简洁性: 展开运算符无疑是最简洁的语法,非常直观。
    • 功能: 同样,展开运算符只能做转换,不能像
      Array.from()
      那样直接集成映射功能。
    • 限制: 展开运算符只能用于可迭代对象。对于只有
      length
      属性和索引但不可迭代的自定义类数组对象(例如上面
      myCollection
      的例子,除非你手动给它添加
      Symbol.iterator
      ),展开运算符是无效的。而
      Array.from()
      依然可以处理。
    • 性能: 在大多数现代 JavaScript 引擎中,这些方法的性能差异通常可以忽略不计,不应成为选择的主要依据,除非你处理极其庞大的数据集。

总结一下:

唱鸭
唱鸭

音乐创作全流程的AI自动作曲工具,集 AI 辅助作词、AI 自动作曲、编曲、混音于一体

下载
  • Array.from()
    是最通用和功能最丰富的选择,它能处理类数组和可迭代对象,并支持一步到位的数据转换。
  • 展开运算符最简洁,但仅限于可迭代对象。
  • [].slice.call()
    是老派但可靠的方法,主要用于兼容性要求高的类数组转换。

我个人在写新代码时,会优先考虑

Array.from()
,因为它功能全面且语义清晰。如果只是简单的可迭代对象转换,展开运算符的简洁性也很吸引人。

Array.from() 的进阶用法和常见误区有哪些?

Array.from()
确实是个多面手,但用起来也有些地方需要注意,避免踩坑。

进阶用法:

  1. 快速生成特定长度和内容的数组: 这个用法非常巧妙,你不需要一个实际的“类数组对象”,只需要一个带有

    length
    属性的对象,就能利用
    Array.from()
    和它的映射函数来生成数组。这比
    new Array(length).fill(value)
    结合
    map
    更加简洁。

    // 生成一个包含1到10数字的数组
    const numbers = Array.from({ length: 10 }, (_, i) => i + 1);
    console.log(numbers); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    // 生成一个包含指定字符重复次数的数组
    const repeatedChars = Array.from({ length: 5 }, () => 'X');
    console.log(repeatedChars); // ['X', 'X', 'X', 'X', 'X']

    这里

    _
    (下划线) 是一个常见的约定,表示我们不关心映射函数接收到的第一个参数(即
    Array.from
    { length: N }
    中取出的
    undefined
    值),只关心索引
    i

  2. 处理

    Set
    map
    对象:
    Set
    map
    都是可迭代对象,
    Array.from()
    可以直接将它们转换为数组。这在需要对
    Set
    map
    的内容进行数组操作时非常有用。

    const uniqueIds = new Set([101, 105, 103, 101]);
    const idArray = Array.from(uniqueIds); // [101, 105, 103]
    
    const userMap = new Map([['id', 1], ['name', 'Alice']]);
    const mapEntries = Array.from(userMap); // [['id', 1], ['name', 'Alice']]
    const mapKeys = Array.from(userMap.keys()); // ['id', 'name']
    const mapValues = Array.from(userMap.values()); // [1, 'Alice']
  3. 使用

    thisArg
    参数:
    Array.from()
    的第三个参数是
    thisArg
    ,它允许你为映射函数指定
    this
    的值。这在映射函数是一个对象方法时特别有用。

    const converter = {
        prefix: 'item-',
        convert(value, index) {
            return this.prefix + value + '-' + index;
        }
    };
    
    const data = [1, 2, 3];
    const convertedData = Array.from(data, converter.convert, converter);
    console.log(convertedData); // ["item-1-0", "item-2-1", "item-3-2"]
    // 如果没有第三个参数 converter,converter.convert 内部的 this 会是 undefined

常见误区:

  1. 不是所有对象都能被转换:

    Array.from()
    并不是万能的。它要求传入的对象要么是“类数组”(有
    length
    属性和索引),要么是“可迭代对象”(实现了
    Symbol.iterator
    接口)。如果你传入一个普通的对象,它既没有
    length
    属性也没有迭代器,那么
    Array.from()
    会返回一个空数组。

    const plainObject = { a: 1, b: 2 };
    const result = Array.from(plainObject);
    console.log(result); // [] (因为 plainObject 既不是类数组也不是可迭代对象)
  2. 浅拷贝的陷阱: 和许多其他数组创建方法一样,

    Array.from()
    执行的是浅拷贝。这意味着如果原始对象或可迭代对象中包含引用类型(如其他对象或数组),那么新数组中存储的将是这些引用,而不是它们的副本。修改新数组中的引用类型元素,会影响到原始数据。

    const originalArray = [{ id: 1 }, { id: 2 }];
    const newArray = Array.from(originalArray);
    
    newArray[0].id = 99;
    console.log(originalArray[0].id); // 99 (原始数组的元素也被修改了)

    如果需要深拷贝,你需要自己实现一个深拷贝逻辑,或者使用像

    JSON.parse(JSON.stringify(obj))
    这样的方式(但它有局限性,比如不能处理函数、
    undefined
    Symbol
    等)。

  3. Array.of()
    的混淆:
    Array.from()
    Array.of()
    名字有点像,但功能完全不同。
    Array.of()
    是用来根据传入的参数创建一个新的数组实例,它解决了
    new Array()
    在传入单个数字参数时的歧义问题。

    // Array.from() 转换现有结构
    Array.from('abc'); // ['a', 'b', 'c']
    
    // Array.of() 根据参数创建新数组
    Array.of(1, 2, 3); // [1, 2, 3]
    Array.of(7);      // [7] (而 new Array(7) 会创建一个长度为7的空数组)

    记住,

    Array.from()
    是“从...来”,
    Array.of()
    是“创建...的”。

掌握这些进阶用法和避开常见误区,能让你更自如、更高效地运用

Array.from()
处理 JavaScript 中的各种数据结构。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

541

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

372

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

727

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

470

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

391

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

990

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

653

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

543

2023.09.20

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
如何进行WebSocket调试
如何进行WebSocket调试

共1课时 | 0.1万人学习

TypeScript全面解读课程
TypeScript全面解读课程

共26课时 | 5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号