0

0

ES6中如何用Array.from转换类数组

煙雲

煙雲

发布时间:2025-07-10 23:41:01

|

635人浏览过

|

来源于php中文网

原创

array.from() 是 es6 中用于将类数组对象或可迭代对象转换为新数组的方法。其语法为 array.from(arraylike, mapfn, thisarg),其中 arraylike 是必填参数,表示要转换的对象;mapfn 和 thisarg 为可选参数,分别用于元素映射和指定 this 上下文。1. 它解决了传统使用 array.prototype.slice.call() 转换类数组对象时语义不清晰、适用范围窄的问题;2. 支持类数组对象(如 arguments、nodelist)和可迭代对象(如 set、map、字符串);3. 提供内置映射功能,在转换过程中即可处理元素;4. 相较于展开运算符(...),array.from 更适用于非可迭代的类数组对象,并能在转换时进行映射;5. 高级应用包括生成数字序列、处理 dom 集合、克隆数组、从字符串创建字符数组等场景。它提升了代码的语义化、可读性和灵活性,是处理数据集合的重要工具

ES6中如何用Array.from转换类数组

ES6 中的 Array.from 方法是用来将类数组对象或可迭代对象转换成一个真正的数组实例。它的出现,极大地简化了我们处理那些“看起来像数组但又不是数组”的数据结构的流程,提供了一种更语义化、更灵活的转换方式。

ES6中如何用Array.from转换类数组

解决方案

Array.from() 静态方法从一个类数组或可迭代对象创建一个新的、浅拷贝的数组实例。它的基本语法是:

Array.from(arrayLike, mapFn, thisArg)
  • arrayLike: 这是一个必需的参数,可以是类数组对象(拥有一个 length 属性和可索引元素,比如 arguments 对象或 NodeList)或者可迭代对象(比如 SetMapString)。
  • mapFn (可选): 一个映射函数,新数组中的每个元素都会经过这个函数的处理。这使得我们可以在转换的同时对元素进行操作,非常方便。
  • thisArg (可选): 执行 mapFn 时使用的 this 值。

举几个例子,你会发现它用起来真的非常直观:

ES6中如何用Array.from转换类数组
// 1. 转换 arguments 对象
function toArray() {
  // arguments 是一个类数组对象
  const args = Array.from(arguments);
  console.log(args); // 比如传入 (1, 2, 3) 会得到 [1, 2, 3]
}
toArray(1, 2, 3);

// 2. 转换 NodeList (例如从 DOM 查询结果)
// 假设 HTML 中有多个 div 元素
// const divs = document.querySelectorAll('div'); // 这是一个 NodeList,不是真正的数组
// const divArray = Array.from(divs);
// console.log(divArray); // 现在你可以对 divArray 使用所有数组方法了,比如 forEach, map, filter

// 3. 转换字符串 (字符串是可迭代的)
const str = "hello";
const charArray = Array.from(str);
console.log(charArray); // ['h', 'e', 'l', 'l', 'o']

// 4. 结合映射函数 (mapFn)
// 生成一个从 0 到 4 的数组,并每个元素翻倍
const numbers = Array.from({ length: 5 }, (v, i) => i * 2);
console.log(numbers); // [0, 2, 4, 6, 8]

// 5. 转换 Set 或 Map
const mySet = new Set([1, 2, 3, 3, 4]);
const setArray = Array.from(mySet);
console.log(setArray); // [1, 2, 3, 4]

const myMap = new Map([['a', 1], ['b', 2]]);
const mapArray = Array.from(myMap);
console.log(mapArray); // [['a', 1], ['b', 2]]

Array.from 的强大之处在于它能处理任何具有 Symbol.iterator 属性的对象(即可迭代对象),以及任何具有 length 属性的对象(即类数组对象),这覆盖了我们日常开发中绝大部分需要转换的场景。

为什么我们需要Array.from?它解决了什么痛点?

Array.from 出现之前,我们处理类数组对象,比如 arguments 或者 document.querySelectorAll() 返回的 NodeList,通常会用一些相对“古老”或者说不那么直观的方法。最常见的就是 Array.prototype.slice.call()

ES6中如何用Array.from转换类数组
// 以前我们可能会这么做
function oldSchoolToArray() {
  const args = Array.prototype.slice.call(arguments);
  console.log(args);
}
oldSchoolToArray(10, 20, 30);

// 或者
// const divs = document.querySelectorAll('div');
// const divArray = Array.prototype.slice.call(divs);

这种写法虽然有效,但总感觉有点别扭,对吧?尤其是对于刚接触 JavaScript 的开发者来说,Array.prototype.slice.call(arguments) 这种链式调用和 call 方法的使用,理解起来门槛稍微高一些。它本质上是借用了 Array.prototype 上的 slice 方法,并强制将 arguments 对象的 this 上下文绑定到 slice 方法上,从而模拟出数组切片的效果,间接实现了转换。

在我看来,Array.from 解决了几个核心痛点:

  1. 语义化和可读性Array.from 的名字本身就非常清晰地表达了它的意图——“从...创建一个数组”。这比 slice.call 这种略显“黑魔法”的写法要好理解得多。代码的可读性提升了,维护起来自然也更轻松。
  2. 更广泛的适用性slice.call 只能处理那些“长得像数组”的对象(有 length 属性和可索引项),但对真正的可迭代对象(比如 SetMap)就无能为力了。而 Array.from 既能处理类数组,也能处理所有可迭代对象,这让它成为了一个更通用的工具。
  3. 内置的映射能力Array.from 的第二个参数 mapFn 是一个非常实用的功能。它允许你在转换的同时对每个元素进行处理,这在很多场景下能省去一次额外的 map 调用。比如,你想把一个 NodeList 转换成数组,并且只取每个元素的 id,用 Array.from 一步到位:
    // const ids = Array.from(document.querySelectorAll('div'), div => div.id);

    这比先转换再 map 要简洁不少。

所以,Array.from 不仅仅是语法糖,它更是对 JavaScript 数组操作能力的一次重要补强和现代化。它让我们的代码更干净、更易懂,也更强大。

Array.from与展开运算符(Spread Operator)有什么区别?何时选择谁?

展开运算符(...)也是 ES6 引入的一个非常强大的特性,它也能将可迭代对象转换成数组,或者用于数组的合并、复制等。例如:

// 使用展开运算符转换字符串
const strSpread = [...'hello'];
console.log(strSpread); // ['h', 'e', 'l', 'l', 'o']

// 转换 Set
const mySetSpread = new Set([1, 2, 3]);
const setArraySpread = [...mySetSpread];
console.log(setArraySpread); // [1, 2, 3]

// 转换 NodeList
// const divsSpread = [...document.querySelectorAll('div')];

看起来它们的功能有些重叠,那我们到底该如何选择呢?这里有一些关键的区别和考量:

  1. 处理对象类型

    • 展开运算符 (...):只能用于可迭代对象。如果一个对象没有实现 Symbol.iterator 接口(例如一个纯粹的类数组对象 {0: 'a', 1: 'b', length: 2}),展开运算符就无法直接将其转换为数组。
    • Array.from():既可以处理可迭代对象,也可以处理类数组对象(只要有 length 属性和可索引项)。这是它比展开运算符更灵活的地方。
    const myCustomArrayLike = { 0: 'apple', 1: 'banana', length: 2 };
    
    // const arr1 = [...myCustomArrayLike]; // 报错:myCustomArrayLike is not iterable
    const arr2 = Array.from(myCustomArrayLike);
    console.log(arr2); // ['apple', 'banana']
  2. 映射功能

    W78CMS企业网站管理系统 (中英繁三语版)1.0 build 100724
    W78CMS企业网站管理系统 (中英繁三语版)1.0 build 100724

    程序采用ASP+ACCESS开发完成。中英繁三语言,所有页面采用UTF-8全球通用编码,兼容简体中文、繁体中文及英语,适用于中小企业网站运用。后台数据同时录入中文及英文,繁体采用JS自动转换,无需维护。免费版主要功能如下:·系统管理:系统综合设置、管理员管理、数据库备份、上传文件管理。·单页管理:自由无限制添加个性页面,如:公司简介、组织结构、联系我们等

    下载
    • 展开运算符 (...):没有内置的映射功能。如果你需要转换并同时对元素进行操作,通常需要先用展开运算符转换,然后再链式调用 map() 方法。
    • Array.from():第二个参数就是 mapFn,可以在转换过程中直接对元素进行映射处理,一步到位。
    const nums = [1, 2, 3];
    
    // 使用展开运算符 + map
    const doubledSpread = [...nums].map(n => n * 2); // [2, 4, 6]
    
    // 使用 Array.from + mapFn
    const doubledFrom = Array.from(nums, n => n * 2); // [2, 4, 6]

    在这个例子中,虽然结果一样,但 Array.from 的写法在语义上更紧凑,尤其是在处理非数组的可迭代对象时,省去了中间步骤。

何时选择谁?

  • 选择展开运算符 (...)

    • 当你的源数据是一个可迭代对象,并且你只需要进行简单的转换(不需要在转换时进行映射)。
    • 追求代码的简洁性和直观性。展开运算符的语法非常简洁明了。
    • 例如:将 Set 转换为数组,或者将 NodeList 转换为数组以使用 forEach 等方法。
  • 选择 Array.from()

    • 当你的源数据是类数组对象但不是可迭代对象(比如上面提到的自定义对象,或者某些旧的 DOM API 返回的类数组集合)。
    • 当你需要在转换的同时对每个元素进行映射或转换mapFn 参数是其独有的优势。
    • 当你需要生成一个特定长度的数组并填充值,例如 Array.from({ length: N }, (_, i) => i) 来生成一个数字序列。
    • 需要更明确的语义,或者处理更复杂的转换逻辑时。

总的来说,对于简单的可迭代对象到数组的转换,展开运算符通常是首选,因为它更简洁。但如果你遇到非可迭代的类数组对象,或者需要在转换过程中进行复杂的数据处理,Array.from() 就会是更强大、更灵活的选择。它们是互补的工具,而不是替代品。

Array.from在实际开发中有哪些高级应用场景?

Array.from 不仅仅是用来转换 argumentsNodeList 那么简单,它的灵活性让它在很多实际开发场景中都能发挥出意想不到的妙用。

  1. 生成数字序列: 这是 Array.from 最常用也最强大的“非传统”用法之一。你不再需要手动循环来创建包含连续数字的数组。

    // 生成一个从 0 到 9 的数组
    const tenNumbers = Array.from({ length: 10 }, (_, i) => i);
    console.log(tenNumbers); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    // 生成一个从 1 到 5 的数组
    const oneToFive = Array.from({ length: 5 }, (_, i) => i + 1);
    console.log(oneToFive); // [1, 2, 3, 4, 5]
    
    // 生成偶数序列
    const evenNumbers = Array.from({ length: 5 }, (_, i) => i * 2);
    console.log(evenNumbers); // [0, 2, 4, 6, 8]

    这在需要创建循环次数、分页页码、图表数据点等场景时,非常方便和简洁。

  2. 处理 DOM 集合,并进行复杂操作: 虽然展开运算符也能将 NodeList 转换为数组,但 Array.from 结合 mapFn 能让你在一步内完成更复杂的转换。

    // 假设页面上有多个带有 data-id 属性的 div
    /* 
    */ // 获取所有 div 的 data-id 属性值,并存储在一个数组中 // const divIds = Array.from(document.querySelectorAll('div'), div => div.dataset.id); // console.log(divIds); // 例如:['item-1', 'item-2']

    这比先转换成数组再 map 看起来更流畅,也更符合函数式编程的风格。

  3. 克隆数组(浅拷贝): 虽然展开运算符 [...arr] 是更常见的数组浅拷贝方式,但 Array.from(arr) 也能实现同样的效果。

    const originalArray = [1, { a: 1 }, 3];
    const clonedArray = Array.from(originalArray);
    console.log(clonedArray); // [1, { a: 1 }, 3]
    console.log(clonedArray === originalArray); // false

    在某些特定场景下,比如统一处理 arrayLikeArray 时,使用 Array.from 可能会带来代码风格上的一致性。

  4. 从字符串创建字符数组(并进行处理): 字符串本身是可迭代的,所以 Array.from 可以将它拆分成字符数组。结合 mapFn,你甚至可以在拆分时就对字符进行转换。

    const word = "JavaScript";
    const upperChars = Array.from(word, char => char.toUpperCase());
    console.log(upperChars); // ['J', 'A', 'V', 'A', 'S', 'C', 'R', 'I', 'P', 'T']

    这对于需要对字符串的每个字符进行独立操作的场景非常有用。

  5. 处理自定义的可迭代对象或类数组对象: 如果你自己定义了一个对象,并为其实现了 Symbol.iterator 接口,或者它只是一个简单的类数组结构,Array.from 都能轻松地将其转换为数组,方便你使用数组的所有方法。

    // 一个简单的自定义迭代器
    const myIterable = {
      *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
      }
    };
    const arrFromIterable = Array.from(myIterable);
    console.log(arrFromIterable); // [1, 2, 3]
    
    // 一个自定义的类数组对象
    const customData = {
      0: 'Alice',
      1: 'Bob',
      2: 'Charlie',
      length: 3
    };
    const arrFromCustomData = Array.from(customData);
    console.log(arrFromCustomData); // ['Alice', 'Bob', 'Charlie']

    这展示了 Array.from 在处理各种数据源时的强大通用性。

总的来说,Array.from 不仅仅是一个简单的转换工具,它更是一个多功能的数组构造器。通过巧妙地利用它的 mapFn 参数以及对各种数据类型的支持,我们可以在代码中实现更简洁、更富有表现力的逻辑。它鼓励我们用更现代、更函数式的方式来思考和处理数据集合。

相关专题

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

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

556

2023.06.20

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

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

374

2023.07.04

js四舍五入
js四舍五入

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

732

2023.07.04

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

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

477

2023.09.01

JavaScript转义字符
JavaScript转义字符

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

414

2023.09.04

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

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

991

2023.09.04

如何启用JavaScript
如何启用JavaScript

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

658

2023.09.12

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

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

552

2023.09.20

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.8万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.9万人学习

ASP 教程
ASP 教程

共34课时 | 3.7万人学习

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

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