本文深入解析 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() 用法总结的介绍。如需了解更多相关内容,请搜索本站往期文章或继续浏览后续文章,感谢大家的支持!