朋友你不会还不知道forEach方法不能终止的结论吧

forEach是我们在日常工作中经常使用到的方法,但是你有什么尝试使用forEach进行停止或终止等操作呢?今天我就遇到了这个问题,借此来剖析一下。

一、走进forEach

之前对于forEach了解的并不多,只知道它可以遍历数组,如果有这么一个操作: 一个数组[0, 1, 2, 3, 4, 5],打印出[0, 1, 2, 3],对于聪明的我可能会这样写。

1.1 尝试return

js 复制代码
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,看看效果会不会好一点。

js 复制代码
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使用

js 复制代码
const arr = [0, 1, 2, 3, 4, 5];

arr.forEach((item, index, arr) => {
	console.log(item, index, arr);
})

遍历的三个值分别为:值、下标、调用方法的数组对象。

2.2 forEach分析

我们先来看一下forEach的特点,为此我专门去MDN上看了一下,得到了以下信息:

js 复制代码
forEach(callbackFn)
  1. 首先接收一个回调callbackFn,回调用三个参数(element, index, array)
    • element:数组中正在处理的当前元素;
    • index:数组中正在处理的当前元素的索引;
    • array:调用了 forEach() 的数组本身。
  2. 函数没有返回值,默认为undefined。

2.3 自定义myForEach

  1. 这里我把自己定义的方法写在数组的原型上,好处就是可复用性, 根据上边得到的信息,我们需要接收一个回调函数(fn),通过for循环改变fn的this指向,具体代码如下: 下面我们来简单分析一下

    js 复制代码
    Array.prototype.myForEach = function (fn) {
    	for (let i = 0; i < this.length; i ++) {
    		fn.call(this, this[i], i, this);
    	}
    }
  2. 使用一下自己写好的myForEach看一下打印的结果

    js 复制代码
    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中。于是我们就想到了下边这种情况它可以终止吗:

js 复制代码
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不能停止。

三、改造myForEach

题外话:我这可能属于是吃饱了没事情做,哈哈。

3.1 想法

试想一下,我们能不能通过改造一下我们自己定义的myForEach方法,来达到满足我们的要求,相信聪明的你也能够想到,让for循环终止,我就简单写一下自己的想法把,我们让fn有返回值,在for循环中通过flag变量接收。

3.2 代码实现

js 复制代码
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
  }
})

ok!完成

四、总结

通过今天的学习,相信自己以后在遇到类似的问题一定会游刃有余。我总是强调基础很重要,学习基础也是一种美。

相关推荐
静默回滚12 分钟前
iPhone照片电脑上打不开:HEIC解码从原理到WASM
前端
dsyyyyy110122 分钟前
Vue 3 Watch 监视完全指南
前端·javascript·vue.js
航飞光电市场经理36 分钟前
人员定位系统“全栈自研”技术解析:从射频前端到定位引擎的架构拆解
前端·架构
Apifox39 分钟前
Apifox 9 月更新|CLI 能力升级、GitLab 私有化部署接入与产品体验优化
前端·后端·测试
deli00740 分钟前
随机乱跳为什么能画出完美三角形:混沌游戏分形实验室
前端
Gizzap_Tech1 小时前
国内官网增加英文版:URL、语言切换与 hreflang 怎么配置?
前端
剪刀石头布啊1 小时前
泛洪DFS、BFS
前端
qetfw1 小时前
Windows Server AD CS:根 CA、Web 证书模板与域内自动注册
前端·windows·windows-server
剪刀石头布啊1 小时前
为什么React组件很少前缀,而vue的不少组件都有前缀
前端
剪刀石头布啊1 小时前
gird网格布局
前端