方法1:使用内置 map() 实现新数组
实现步骤
首先明确你需要对数组中的每个元素进行的变换,确保变换逻辑在回调中是纯函数,避免副作用影响结果。
接着对原始数组直接调用 Array.prototype.map,该方法会逐项执行回调,返回一个新数组,不会修改原数组。
最后将返回的新数组作为结果进行后续处理,注意保持输入输出的一致长度,以确保映射后的数组长度等于输入长度。
性能分析
时间复杂度为 O(n),其中 n 是输入数组长度,回调函数会对每个元素执行一次映射逻辑。
在实现细节上,map 内部会迭代并构造新数组,但回调函数的调用会带来一定开销,尤其当回调较复杂或包含额外分支时。
在多数现代浏览器中,map 的执行速度接近原生循环,或略慢于极端优化的 for 循环,但可读性和函数式风格带来额外的开发便利性。
const nums = [1, 2, 3, 4];
const doubled = nums.map(n => n * 2);方法2:使用 for 循环 + push 实现新数组
实现步骤
这是直观且通常最可控的一种实现,通过显式循环逐项计算并放入新数组。
步骤要点包括:初始化一个空数组,遍历输入数组,对每个元素执行映射表达式后放入结果数组。
对于需要更高性能的场景,你也可以先创建一个同长度的空数组再赋值,而不是每次 push。
性能分析
时间复杂度同样为 O(n),但通常在没有回调开销的情况下,for 循环的执行会更接近硬件层面的优化。
与 map 相比,避免了回调函数调用的额外成本,在短循环或对性能敏感的场景下可能更快。
需要注意的是,使用 push 可能会产生动态扩容的开销,而若事先分配等长的数组后再赋值,性能可能更稳定。
const nums = [1, 2, 3, 4];
const res = [];
for (let i = 0; i < nums.length; i++) {res.push(nums[i] * 2);
}方法3:使用 reduce 实现新数组
实现步骤
reduce 可以在遍历的同时累积结果,将映射的结果逐步推入累积数组。

关键点是:将初始累积值设为一个空数组,在回调中对每个元素计算映射结果后使用 acc.push() 将其加入到累积数组中。
此方法的可读性稍差于 map,但在某些函数式风格的代码库中很常见且灵活。
性能分析
时间复杂度为 O(n),但被广泛认为在函数调用开销上略逊于 for 循环和直接 map 使用。
由于每次迭代都要执行回调并操作数组,reduce 的性能往往处于三者中的中间位置,在需要与其他聚合逻辑结合时具有优势。
const nums = [1, 2, 3, 4];
const res = nums.reduce((acc, v) => {acc.push(v * 2);return acc;
}, []);方法之间的性能对比
对比要点
三种映射新数组的核心都是 时间复杂度 O(n),但在实际运行时的常量开销不同。
在大多数引擎中,原生 map 的回调被高度优化,通常比由循环控制的实现略快或相近,但差异往往在微秒级别。
对于需要最小化回调开销的场景,for 循环 + 直接赋值/推入实现通常具有更低的常量因子,从而在极端性能敏感的循环中占优。
适用场景与注意点
如果你的目标是代码可读性、函数式风格和链式调用,map 是最自然的选择。当你需要在循环中执行额外的逻辑或早中止遍历时,for 循环提供了更大的灵活性。
使用 reduce 时,请确保回调函数尽量简洁,以避免性能下降;同时它在与其他聚合操作耦合时具备额外的表达力。


