避免频繁的数组扩容
在处理大量数据时,如果不断往数组里添加元素,比如用 JavaScript 的 push 方法,系统可能会反复触发内存重新分配。就像搬家时不断往纸箱里塞东西,塞满了再换更大的箱子,来回折腾很费时间。提前预估数据量,初始化一个合适大小的数组能省不少事。
// 不推荐:边循环边 push,可能多次扩容
let arr = [];
for (let i = 0; i < 100000; i++) {
arr.push(i);
}
// 推荐:预先分配长度
let arr = new Array(100000);
for (let i = 0; i < 100000; i++) {
arr[i] = i;
}优先使用索引访问而非高阶函数
像 map、filter 这些方法写起来简洁,但每次都会创建新数组并遍历所有元素。如果只是想读取或修改数据,直接用 for 循环访问索引效率更高。
// 耗时较长
const doubled = items.map(x => x * 2);
// 更快的方式
const doubled = new Array(items.length);
for (let i = 0; i < items.length; i++) {
doubled[i] = items[i] * 2;
}减少嵌套循环操作
两个数组做对比查找时,很容易写出双重 for 循环。这种写法在数据量稍大时性能急剧下降。可以用对象或 Set 把查找变成常数时间,就像从杂乱抽屉翻东西变成查标签柜子,快得多。
// O(n²) 性能差
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
if (arr1[i] === arr2[j]) {
// 找到了
}
}
}
// O(n) 优化版本
const set2 = new Set(arr2);
for (const item of arr1) {
if (set2.has(item)) {
// 找到了
}
}慎用数组拼接和切片
频繁使用 concat 或 slice 会产生大量中间数组,占用内存。如果是合并多个数组,考虑用 push.apply 或扩展运算符配合预分配空间。
// 内存抖动大
let result = [];
for (const part of chunks) {
result = result.concat(part);
}
// 更高效的做法
let result = [];
for (const part of chunks) {
Array.prototype.push.apply(result, part);
}利用缓存提升重复访问效率
如果要在循环中反复获取数组长度,别每次都调用 arr.length。虽然看起来只是个属性,但在某些环境或代理数组中可能有计算开销。把它存成变量,就像出门前看一次手表,而不是每走一步都看一眼。
for (let i = 0, len = arr.length; i < len; i++) {
// 使用 arr[i]
}