JavaScript Array.from() 方法详解与实战应用

作者:青柠时间:2026-10-30 19:04:30浏览:657

本文深入解析 JavaScript 中 Array.from() 方法的用法。该方法可将类数组对象和可迭代对象(如字符串、Set、Map)转换为真正的数组实例。文章详细说明了其语法结构、可选参数 mapFn 与 thisArg 的作用,并通过代码示例展示了其在 NodeList 转换、序列生成及稀疏数组处理中的实际应用,同时对比了其与 Array.map() 的性能差异。

前言

尽管 Array.from() 方法已存在一段时间且常被使用,但许多开发者对其内部机制仍不够清晰。本文将系统梳理该方法的原理与用法,帮助读者彻底掌握这一工具。

根据官方文档定义,Array.from() 是一个静态方法,用于从类数组对象(array-like object)或可迭代对象(iterable object)创建一个新的、浅拷贝的数组实例。

核心要点在于输入源必须是可迭代对象或类数组对象。

语法

Array.from(arrayLike)
Array.from(arrayLike, mapFn)
Array.from(arrayLike, mapFn, thisArg)

参数说明

  • arrayLike:期望转换为数组的类数组对象或可迭代对象。类数组对象特指拥有 length 属性及索引元素的对象。
  • mapFn 可选:调用数组每个元素的函数。如果提供,每个将要添加到数组中的值首先会传递给该函数,然后将 mapFn 的返回值增加到数组中。使用以下参数调用该函数:
    • mapFn:可选参数,指定数组中每个元素在添加前需调用的映射函数。若提供此参数,每个待添加的值将先通过该函数处理,其返回值才会被加入新数组。调用该函数时传入以下参数:
    • element:数组当前正在处理的元素值。
  • index:当前处理元素在数组中的索引位置。

返回值

返回一个新的数组实例。

使用场景

字符串转换

Array.from("foo");
// [ "f", "o", "o" ]

Set 集合转换

const set = new Set(["foo", "bar", "baz", "foo"]);
Array.from(set);
// [ "foo", "bar", "baz" ]

Map 对象转换

const map = new Map([
  [1, 2],
  [2, 4],
  [4, 8],
]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]
const mapper = new Map([
  ["1", "a"],
  ["2", "b"],
]);
Array.from(mapper.values());
// ['a', 'b'];
Array.from(mapper.keys());
// ['1', '2'];

注意 new Map() 与普通对象 {} 的区别

const map = {
    0: 1,
    1: 2,
    3: 4,
}
let result = Array.from(map)
console.log(result) // []

为 Map 对象添加 length 属性

const map = {
    0: 1,
    1: 2,
    3: 4,
    length: 3
}
let result = Array.from(map)
console.log(result) // [ 1, 2, undefined ]

将 length 属性值修改为 4

console.log(result) // [ 1, 2, undefined, 4 ]

当对象具备 length 属性时,即被视为类数组对象。Array.from() 默认从索引 0 开始遍历并将元素加入新数组。上述示例中 Array.from() 省略了 mapFn,其效果等同于直接使用默认行为。

let result = Array.from(map, (v, i) => v)

这种写法更为直观,表明 Array.from 是通过读取 length 属性进行遍历,并逐个取值构建新数组的。

NodeList 转换

// 根据 DOM 元素的属性创建一个数组
const images = document.querySelectorAll("img");
const sources = Array.from(images, (image) => image.src);
const insecureSources = sources.filter((link) => link.startsWith("http://"));

箭头函数应用

// 使用箭头函数作为映射函数去
// 操作多个元素
Array.from([1, 2, 3], (x) => x + x);
// [2, 4, 6]
// 生成一个数字序列
// 因为数组在每个位置都使用 `undefined` 初始化,
// 下面的 `v` 值将是 `undefined`
Array.from({ length: 5 }, (v, i) => i);
// [0, 1, 2, 3, 4]

稀疏数组处理

console.log(Array.from([,,3,4])) // [ undefined, undefined, 3, 4 ]

序列生成器

// 序列生成器函数(通常称为“range”,例如 Clojure、PHP 等)
const range = (start, stop, step) =>
  Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step);
// 生成的数字范围 0..4
range(0, 4, 1);
// [0, 1, 2, 3, 4]
// 生成的数字范围 1..10,步长为 2
range(1, 10, 2);
// [1, 3, 5, 7, 9]
// 使用 Array.from 生成字母表,并将其序列排序
range("A".charCodeAt(0), "Z".charCodeAt(0), 1).map((x) =>
  String.fromCharCode(x),
);
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

在非数组构造函数上调用 from()

from() 方法可在任何构造函数上调用,前提是该构造函数接受一个表示新数组长度的单一参数。

function NotArray(len) {
  console.log("NotArray called with length", len);
}
// 可迭代对象
console.log(Array.from.call(NotArray, new Set(["foo", "bar", "baz"])));
// NotArray called with length undefined
// NotArray { '0': 'foo', '1': 'bar', '2': 'baz', length: 3 }
// 类数组对象
console.log(Array.from.call(NotArray, { length: 1, 0: "foo" }));
// NotArray called with length 1
// NotArray { '0': 'foo', length: 1 }

当 this 值并非构造函数时,该方法将返回一个普通的数组对象。

console.log(Array.from.call({}, { length: 1, 0: "foo" })); // [ 'foo' ]

与 Array.map() 的区别

Array.from(obj, mapFn, thisArg) 与 Array.from(obj).map(mapFn, thisArg) 产生的结果相同,但前者不会创建中间数组,且 mapFn 仅接收两个参数(element、index),不接收数组本身,因为数组仍在构建过程中。

Array.map(mapFn, thisArg) 中的 mapFn 接收三个参数(element、index、array),其中 array 为调用 map() 方法的数组实例。

在大多数场景下,Array.from() 可基本替代 Array.map() 方法,尤其在需要避免中间数组创建时更具优势。

总结

Array.from(arrayLike, mapFn, thisArg) 接收三个参数,后两个为可选参数,最终返回一个非稀疏的数组实例。该数组实例可直接从可迭代对象(如 String、Map、Set)生成。

const map = {
    0: 1,
    1: 2,
    3: 4,
    length: 3
}
console.log(Symbol.iterator in map) // false
console.log(Symbol.iterator in new String('1123')) // true
console.log(Symbol.iterator in new Map()) // true
console.log(Symbol.iterator in new Set()) // true

此外,Array.from() 也能从类数组对象生成新数组。

Array.from({ length: 5 }, (v, i) => i); // [0, 1, 2, 3, 4]

Array.from() 在功能上基本可替代 Array.map() 方法,且性能更优。

参考

Array.from() - JavaScript | MDN (mozilla.org)

到此结束关于 JavaScript 中 Array.from() 用法总结的介绍。如需了解更多相关内容,请搜索本站往期文章或继续浏览后续文章,感谢大家的支持!

作者最新文章

相关标签: