JavaScript forEach 和 for 区别

平时写代码时,循环是我们用得最多的操作之一——不管是遍历购物车商品、筛选待办事项,还是统计页面元素数量,都离不开循环。很多新手刚学JavaScript时,常会纠结用forEach还是普通for循环,总觉得“都是循环,随便用呗”,其实两者差得还挺多,用错了不仅会多写多余代码,甚至会藏出bug。

先搞懂:两者的“循环对象”不一样

举个最生活化的例子:你手里拿着一串糖葫芦,每颗山楂就是循环里要处理的元素。普通for循环就像是你从第一颗山楂开始数,数到最后一颗就停,整个过程你全程自己掌控:你决定什么时候开始、什么时候结束,甚至中途想停就停。

JavaScript forEach 和 for 区别

而forEach更像是别人帮你拿着糖葫芦,你只需要说“每吃一颗就告诉我一声,顺便帮我记个数”,你不用管自己怎么移动、什么时候停下,只需要告诉别人“每一步要做什么”——但你没法自己中途叫停,必须把整串糖葫芦吃完。

放到代码里,普通for循环是基于“索引”操作的,你可以自己定义循环的起始位置、终止条件、步长,比如从数组第2个元素开始,每2个元素取一次,中途遇到某个值就直接跳出:

`javascript

const fruits = ['苹果', '香蕉', '橙子', '葡萄'];

// 普通for循环:从索引1开始,遇到'橙子'就退出

for (let i = 1; i < fruits.length; i++) {

if (fruits[i] === '橙子') break;

console.log(fruits[i]); // 只会打印'香蕉'

}

`

而forEach是数组的方法,它的参数是一个“回调函数”,专门用来处理每一个元素,默认会遍历数组的每一项,没法用break或return中途退出循环,一上来就把所有元素都过一遍:

`javascript

const fruits = ['苹果', '香蕉', '橙子', '葡萄'];

// 试一下用break,直接报错

fruits.forEach(fruit => {

if (fruit === '橙子') break; // Uncaught SyntaxError: Illegal break statement

console.log(fruit);

});

`

这就像你给外卖员说“帮我把这串糖葫芦挨个送出去”,但你没法中途说“停,我不要后面的了”,必须等外卖员把所有山楂都送完才行。

再看:变量作用域的差异,藏bug的隐形坑

还是用糖葫芦的例子:普通for循环里的索引变量(比如i),如果是用let声明的,每一轮循环都会生成一个新的变量,不会互相干扰;但如果不小心用了var,就会出现全局变量的问题,这是新手最容易踩的坑。

比如我们要给每个按钮加点击事件,想点击第3个按钮就打印它的索引:

`html

<button>按钮1</button>

<button>按钮2</button>

<button>按钮3</button>

`

如果用var声明i,用普通for循环写:

`javascript

var buttons = document.querySelectorAll('button');

for (var i = 0; i < buttons.length; i++) {

buttons[i].addEventListener('click', () => {

console.log(i); // 不管点哪个按钮,都打印3

});

}

`

为什么?因为var的作用域是全局的,循环结束后i的值已经变成3,所有点击事件拿到的都是同一个i。如果改成let声明,就不会有这个问题,每一轮的i都是独立的。

而forEach里的回调函数,每一轮的元素和索引都是回调函数自己的局部变量,不会和外部变量冲突,刚才的例子用forEach写就不会出错:

`javascript

var buttons = document.querySelectorAll('button');

buttons.forEach((button, index) => {

button.addEventListener('click', () => {

console.log(index); // 点按钮1打0,点按钮2打1,点按钮3打2

});

});

`

这就像你让不同的小朋友分糖葫芦,每个小朋友只负责自己手里的那一颗,不会抢别人的;但用var的for循环,就像所有小朋友都盯着最后一颗糖葫芦,结果都抢同一颗。

选哪个?根据场景定就好

如果只是简单遍历数组,不需要中途退出,也不需要额外控制循环,用forEach写起来更简洁,代码也更易读;但如果需要中途跳出循环(比如找某个元素后就不用继续),或者要处理非数组的循环场景(比如遍历对象的键),普通for循环就更灵活。

其实两者没有绝对的好坏,适合当前需求的就是最好的——不用为了追求“高级写法”硬用forEach,也不用觉得老的for循环过时,选对场景就能少踩坑。

上一篇 C/C++编程的核心优势与入门必备基础知识科普