网站首页 > 文章精选 正文
在 JavaScript 中,当我们需要创建一个特定长度或内容的数组时,脑海里第一个闪过的念头可能就是 for 循环。
// 需求:创建一个长度为 5,内容为 [0, 1, 2, 3, 4] 的数组
const arr = [];
for (let i = 0; i < 5; i++) {
arr.push(i);
}
这当然没问题,但有没有更优雅、更函数式的方式呢?
今天,就让我们来认识一下数组的“创造魔法师”——Array.from()。它不仅能将类数组对象和可迭代对象转换为真正的数组,其强大的第二个参数(一个 map 函数)更是能让我们玩出各种花样,彻底告别繁琐的 for 循环初始化。
用法一:创建数字序列(替代 for循环)
这是最基础也是最实用的一个用法。Array.from() 的第一个参数可以是一个具有 length 属性的对象。
// 需求:创建一个长度为 5,值为 [0, 1, 2, 3, 4] 的数组
// 老办法:for 循环
const arr1 = [];
for (let i = 0; i < 5; i++) {
arr1.push(i);
}
// 神仙用法:Array.from()
const arr2 = Array.from({ length: 5 }, (value, index) => index);
console.log(arr2); // [0, 1, 2, 3, 4]
解析:
- { length: 5 }:我们创建了一个类似数组的对象,它只有 length 属性。
- (value, index) => index:这是 Array.from() 的第二个参数,一个映射函数。它会对新数组的每一个位置都执行一次。
- index 是当前元素的索引 (0, 1, 2, 3, 4)。
- value 在这种情况下是 undefined,因为 { length: 5 } 对象没有实际的值。
- 我们直接返回 index 作为新数组元素的值。
就这样,一行代码就优雅地替代了整个 for 循环。
用法二:生成特定规则的数组
for 循环能做的,Array.from() 都能做得更漂亮。比如,生成一个由偶数组成的数组,或者一个平方数序列。
// 需求 1:创建一个包含 5 个偶数的数组 [0, 2, 4, 6, 8]
const evens = Array.from({ length: 5 }, (_, i) => i * 2);
console.log(evens); // [0, 2, 4, 6, 8]
// 需求 2:创建一个包含 1 到 5 的平方的数组 [1, 4, 9, 16, 25]
const squares = Array.from({ length: 5 }, (_, i) => (i + 1) ** 2);
console.log(squares); // [1, 4, 9, 16, 25]
// 需求 3:创建 5 个内容相同的元素
const fives = Array.from({ length: 5 }, () => 5);
console.log(fives); // [5, 5, 5, 5, 5]
技巧:如果我们在映射函数中用不到 value 参数,可以用下划线 _ 来占位,这是一种广为接受的代码风格,表示“这个参数我故意忽略了”。
用法三:快速初始化对象数组
在写测试用例或 mock 数据时,我们经常需要创建一组结构相同的对象。Array.from() 在这个场景下简直是神器。
// 需求:创建一个包含 3 个用户的数组,每个用户有 id 和一个随机分数
const users = Array.from({ length: 3 }, (_, i) => ({
id: i + 1,
score: Math.floor(Math.random() * 101) // 0-100 的随机分
}));
console.log(users);
/*
输出示例:
[
{ id: 1, score: 83 },
{ id: 2, score: 15 },
{ id: 3, score: 99 }
]
*/
一行代码,一个结构清晰、内容随机的对象数组就诞生了。是不是比写三遍 for 循环 push 一个对象要爽得多?
用法四:复制并深度处理数组
Array.from() 不仅能从零创建,还能基于现有数组进行“深加工”。它在转换的同时进行映射,一步到位,避免了先 map 再 filter 等可能产生的中间数组。
const original = [1, '2', 3, null, '4', 5];
// 需求:从一个混合数组中,只提取出数字,并将非数字转为 0
// 返回 [1, 0, 3, 0, 0, 5]
const processed = Array.from(original, item => {
const num = Number(item);
return isNaN(num) ? 0 : num;
});
console.log(processed); // [1, 2, 3, 0, 4, 5] <-- 修正:Number('2') 是 2,Number(null) 是 0
// Let's correct the example to be more illustrative
// 需求:将所有数字乘以2,非数字项保持为 null
const processedV2 = Array.from(original, item => {
return typeof item === 'number' ? item * 2 : null;
});
console.log(processedV2); // [2, null, 6, null, null, 10]
对比 map:
Array.from(array, mapFn) 的效果和 array.map(mapFn) 几乎一样。但 Array.from 的优势在于它的第一个参数可以是类数组对象。
比如,处理函数的 arguments 对象或者 DOM 查询结果 NodeList。
function sumArguments() {
// arguments 是一个类数组对象,它没有 .map 方法
// return arguments.map(x => x * 2); // Uncaught TypeError: arguments.map is not a function
// 用 Array.from 就可以轻松处理
const argsArray = Array.from(arguments);
return argsArray.reduce((sum, num) => sum + num, 0);
}
console.log(sumArguments(1, 2, 3, 4)); // 10
用法五:巧妙生成字母序列
谁说只能处理数字?Array.from() 结合字符编码,可以轻松生成字母表。
// 需求:生成一个从 'A' 到 'Z' 的字母数组
const alphabet = Array.from({ length: 26 }, (_, i) => {
// 'A' 的 ASCII 码是 65
return String.fromCharCode(65 + i);
});
console.log(alphabet);
// ["A", "B", "C", ..., "Z"]
这个用法虽然不常用,但它绝佳地展示了 Array.from() 的灵活性和表现力,是面试中展示我们技术深度的小亮点。
猜你喜欢
- 2025-07-28 字节SOLO超详细实战测评!到底能否实现一行代码不写就上线?!
- 2025-07-28 深入浅出全栈工程师: 如何编写测试
- 2025-07-28 接口测试流程是怎样的?(接口测试入门教程)
- 2025-07-28 优酷质量保障系列(三)—移动端组件智能测试方案
- 2025-07-28 前端开发的终局是"全栈"?从SSR到RSC,离"零API"开发还有多远?
- 2025-07-28 【Python神器】你可能忽视了的 itertools 模块
- 2025-07-28 程序员好物推荐之Yapi(程序员必备神器)
- 2025-07-28 手摸手,带你用vue撸后台(vue hook)
- 2025-07-28 写 Python 七年才发现的七件事:真正提高生产力的脚本思路
- 2025-07-28 TypeScript Enum 的隐藏问题,你中招了吗?
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)
- fmt.println (52)