在写代码时,经常要处理一堆数据,比如用户的订单记录、商品列表或者学生成绩。这些数据通常存放在数组里,想一个个查看或修改,就得靠循环结构遍历数组。这操作看起来简单,但用不好容易出问题,轻则程序卡住,重则数据错乱。
为什么需要遍历数组
假设你在做一个小型库存系统,有一组商品信息存在数组中:
const products = ['苹果', '香蕉', '橙子'];
你想把每个商品名称打印出来,总不能手动写三次 console.log 吧?这时候就得上循环了。
常见的遍历方式
JavaScript 里最常用的几种写法是 for 循环、for...of 和 forEach。
传统 for 循环写法灵活,控制力强:
for (let i = 0; i < products.length; i++) {
console.log(products[i]);
}
for...of 更简洁,适合只读场景:
for (const item of products) {
console.log(item);
}
如果想配合函数式编程风格,forEach 也不错:
products.forEach(function(item) {
console.log(item);
});
容易踩的坑
有人写 for 循环时习惯把 length 放进条件里,但如果在循环过程中数组变了,就可能出问题。比如一边遍历一边删元素:
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) {
arr.splice(i, 1); // 删除当前项
}
}
这样会跳过下一个元素,因为索引已经变了。解决办法是倒着遍历,或者用 filter 创建新数组。
性能上的小细节
在老式浏览器或性能敏感场景下,把数组长度缓存一下能省点开销:
for (let i = 0, len = products.length; i < len; i++) {
console.log(products[i]);
}
虽然现代引擎大多会优化这个,但养成习惯也没坏处。
实际排查案例
有次同事说页面卡死,查下来发现是个无限循环。原因是他在遍历数组时不断往里面 push 数据:
for (let i = 0; i < list.length; i++) {
list.push(processData(list[i]));
}
length 一直在变大,i 永远追不上,CPU 直接飙到 100%。后来改成先复制原数组再处理,问题就解决了。
还有一种情况是嵌套循环时变量名写混了,外层和内层都用了 i,结果外层循环被干扰。建议变量命名清晰些,比如用 row、col 或者 indexItem 这类名字。
别忘了空数组的情况
很多代码默认数组有内容,一旦传进来的是空数组,逻辑就断了。最好加个判断:
if (Array.isArray(data) && data.length > 0) {
for (const item of data) {
// 处理逻辑
}
}
这样程序更健壮,不容易因为一个空数组整个崩溃。