Array.from() 的 5 个神仙用法,彻底告别 for 循环初始化!


在 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 属性的对象。

** 解析: **

  1. { length: 5 } :我们创建了一个类似数组的对象,它只有 length 属性。
  2. (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() 在这个场景下简直是神器。

一行代码,一个结构清晰、内容随机的对象数组就诞生了。是不是比写三遍 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

用法五:巧妙生成字母序列

谁说只能处理数字? 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() 的灵活性和表现力,是面试中展示我们技术深度的小亮点。