让数组操作更优雅:深挖Array.from
在日常的前端开发中,我们经常需要对数据进行转换、处理。在面对类数组对象和可迭代对象的处理时, 我们的 forEach
、map
等常用的数组方法似乎显得有些吃力。比如,我们处理 document.querySelectorAll
返回的 NodeList
类数组对象集合,用forEach
就是为难自己。这时候,Array.from
就能派上用场,帮助我们以更优雅的方式实现需求。
Array.from 是什么
Array.from
是一个静态方法,用于从以下数据类型生成数组:
- 类数组对象: 包含
length
属性的对象,例如arguments
。 - 可迭代对象: 可以被迭代的对象,例如
Map
、Set
或String
对象。
类数组对象与可迭代对象的区别
特性 | 类数组对象 | 可迭代对象 |
---|---|---|
核心特征 | 拥有 length属性和索引键 | 实现了 [Symbol.iterator] 方法 |
是否支持迭代 | 不支持(for...of无法遍历) | 支持(for...of可遍历) |
是否具备数组方法 | 否 | 不一定,具体视对象而定常见 |
例子 | arguments、NodeList | Array、String、Set、Map |
Array.from语法
Array.from(arrayLike, mapFn, thisArg);
参数 | 描述 | 备注 |
---|---|---|
arrayLike | 必须。类数组对象或可迭代对象。 | |
mapFn | 可选。对每个元素调用的映射函数,相当于 Array.prototype.map。 | |
thisArg | 可选。指定 mapFn 中 this 的值。 |
基本用法
字符串转数组
字符串是可迭代对象,Array.from
可以将其直接转换为字符数组:
const str = "快乐就是哈哈哈";
const charArray = Array.from(str);
console.log(charArray); // ['快', '乐', '就', '是', '哈', '哈', '哈']
2
3
将 arguments 转换为数组
函数中的 arguments
是类数组对象,用 Array.from
可以轻松转为数组,方便操作:
function toArray() {
const argsArray = Array.from(arguments);
console.log(argsArray);
}
toArray("你好", "我是", "快乐就是哈哈哈"); // ["你好", "我是", "快乐就是哈哈哈"]
2
3
4
5
arguments
是 JavaScript 函数中一个内置的类数组对象,它包含了函数调用时传入的所有参数。即使函数没有定义参数,arguments
也可以捕获调用时的所有传参。
从集合(Set)或映射(Map)中生成数组
const set = new Set(["马龙", "樊振东", "许昕"]);
console.log(Array.from(set)); // ['马龙', '樊振东', '许昕']
// 使用中国的地名及其相关信息创建一个Map对象
const map = new Map([
["北京", "中国的首都"],
["西安", "我家"],
["XX", "你家"]
]);
console.log(Array.from(map)); // [['北京', '中国的首都'], ['西安', '我家'], ['XX', '你家']]
2
3
4
5
6
7
8
9
10
mapFn 的妙用
Array.from
提供了一个映射函数 mapFn
,可以在生成数组时直接对元素进行处理。
对数据进行包装
const nums = [1, 2, 3, 4];
const squares = Array.from(nums, num => num ** 2);
console.log(squares); // [1, 4, 9, 16]
2
3
从字符串中提取 ASCII 码
const chars = "ABC";
const asciiCodes = Array.from(chars, char => char.charCodeAt(0));
console.log(asciiCodes); // [65, 66, 67]
2
3
动态生成范围数组
通过 mapFn
,我们可以快速生成一个特定范围的数组:
const range = (start, end) => Array.from(
{ length: end - start + 1 },
(_, i) => start + i
);
console.log(range(5, 10)); // [5, 6, 7, 8, 9, 10]
2
3
4
5
上述代码中,我们使用 { length: end - start + 1 }
创建了一个指定长度的类数组对象。
使用对象字面量 { length: ... }
创建一个类数组对象,其长度为 end - start + 1
,表示范围内数字的总数。
超实用场景
去除数组中的空值
Array.from
可以配合 filter
清理数据:
const rawData = [1, , 2, null, 3, undefined, 4];
const cleanedData = Array.from(rawData, item => item || 0);
console.log(cleanedData); // [1, 0, 2, 0, 3, 0, 4]
2
3
批量操作dom
将 DOM 查询结果转换为数组,便于使用数组方法:
const divs = document.querySelectorAll("div");
const divArray = Array.from(divs);
console.log(divArray); // [div, div, div, ...]
2
3
结合Set实现去重效果
利用 Set
去重后,再通过 Array.from
转为数组:
const nums = [1, 2, 2, 3, 4, 4];
const uniqueNums = Array.from(new Set(nums));
console.log(uniqueNums); // [1, 2, 3, 4]
2
3
上述代码的去重原理如下:
- 使用 Set去重:
- Set 是一个集合数据结构,它不允许有重复的值。
- 当我们将一个数组(如 nums)转换为 Set 时,Set 会自动去除数组中的重复元素。
- 转换回数组:
- 由于 Set 不是数组,如果我们需要得到一个数组形式的结果,可以使用 Array.from 方法将 Set 转换回数组。
当然,不使用Array.from也可以实现:
const nums = [1, 2, 2, 3, 4, 4];
const uniqueNums = [...new Set(nums)]; // 也可以使用扩展运算符(...)代替Array.from
console.log(uniqueNums); // [1, 2, 3, 4]
2
3
结语
Array.from 是一个灵活且功能强大的工具,能轻松将类数组或可迭代对象转化为数组,还可以通过映射函数完成各种复杂的处理。在处理字符串、DOM 集合、范围生成和数据去重时,它能让代码更加优雅、简洁。