JS中为什么forEach方法不能终止
forEach
是我们在日常工作中经常使用到的方法,但是你有什么尝试使用forEach
进行停止
或终止
等操作呢?一、走进forEach
对于
forEach
了解不多的,只知道它可以遍历数组,如果有这么一个操作: 一个数组[0, 1, 2, 3, 4, 5]
,打印出[0, 1, 2, 3]
,可能会这么写。
1.1 尝试return
1 2 3 4 5 6 7 8 9 10 11 | const arr = [0, 1, 2, 3, 4, 5]; const newArr = []; arr.forEach(item => { newArr.push(item); if (item === 3) { return false ; } }) console.log(newArr); // ??? |
打印的结果不尽人意
,还是 [0, 1, 2, 3, 4, 5]
。为什么会这样呢?
首先我们得出了一个结论,forEach不能通过return终止运行
。
1.2 尝试break
我们在尝试一下for
循环中的break
,看看效果会不会好一点。
1 2 3 4 5 6 7 8 9 10 11 | const arr = [0, 1, 2, 3, 4, 5]; const newArr = []; arr.forEach(item => { newArr.push(item); if (item === 3) { break ; // SyntaxError: Illegal break statement } }) console.log(newArr); // ??? |
结果报错了
:语法错误,非法的break语句。
二、剖析forEach
对于上边的结果,我们就来看一看forEach
的实现原理
到底是怎么样的,我猜想万变不离其宗,说到底还是for循环
。
2.1 forEach使用
1 2 3 4 5 | const arr = [0, 1, 2, 3, 4, 5]; arr.forEach((item, index, arr) => { console.log(item, index, arr); }) |
遍历的三个值分别为:值、下标、调用方法的数组对象
2.2 forEach分析
我们先来看一下forEach的特点,为此我专门去MDN上看了一下,得到了以下信息:
1 | forEach(callbackFn) |
- 首先接收一个回调
callbackFn
,回调用三个参数(element, index, array)element
:数组中正在处理的当前元素;index
:数组中正在处理的当前元素的索引;array
:调用了 forEach() 的数组本身。
- 函数没有返回值,默认为
undefined
。
2.3 自定义myForEach
-
这里我把自己定义的方法写在数组的原型上,好处就是可复用性, 根据上边得到的信息,我们需要接收一个
回调函数(fn)
,通过for循环
改变fn的this指向
,具体代码如下: 下面我们来简单分析一下
1 2 3 4 5 | Array.prototype.myForEach = function (fn) { for ( let i = 0; i < this .length; i ++) { fn.call( this , this [i], i, this ); } } |
2. 使用一下自己写好的myForEach
看一下打印的结果
const arr = [0, 1, 2, 3, 4, 5]; arr.myForEach((item, index, arr) => { console.log(item, index, arr); })
不能说完全相同只能说是一模一样
。
2.4 深入解析forEach
通过2.3
我们可以看到我们的for循环中是一个函数执行,我们最开始的写法就是说我们的return
和break
是写在了我们的fn
中。于是我们就想到了下边这种情况它可以终止吗:
const arr = [0, 1, 2, 3, 4, 5]; for (let i = 0; i < arr.length; i ++) { fn(arr[i], i, arr); } function fn (item, index, array) { console.log(item, index, arr); if (item === 3) { return false; } }
显然这样是不可以的,所以forEach不能停止
。
p.s 有一种不推荐的做法是可以终止的,就是在循环体里抛出异常。
eg.
输出
三、改造myForEach
题外话:我这可能属于是吃饱了没事情做,哈哈
。
3.1 想法
试想一下,我们能不能通过改造一下我们自己定义的myForEach
方法,来达到满足我们的要求,相信聪明的你也能够想到,让for循环终止
,我就简单写一下自己的想法把,我们让fn有返回值
,在for
循环中通过flag变量
接收。
3.2 代码实现
Array.prototype.myForEach = function (fn) { for (let i = 0; i < this.length; i++) { const flag = fn.call(this, this[i], i, this); if (flag) { break } } } const arr = [0, 1, 2, 3, 4, 5]; arr.myForEach((item, index, array) => { console.log(item, index, array) if (item === 3) { return true } })
p.s jq的each就是return false中断的,都是大同小异。
四、总结
如果一定要跳出当前循环的操作,就不要用forEach。直接用for或者是其他循环函数。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?