forEach无法跳出循环的自我理解

最近写代码才偶然发现forEach无法用return跳出循环,有朋友说用break可以跳出,感觉这个解决方案很瞎,试了试确实很瞎!首先break是用在循环体中的,forEach虽然是循环,但是代码写在回调函数里,这一点就直接决定forEach不能使用break。

let arr=[0,1,2,3,4,5];
//示例1:
arr.forEach(v=>{
    console.log(v);//输出结果:0,1,2,3,4,5
    if(v>3){
        return;
    }
})
//示例2:
arr.forEach(v=>{
    if(v<3){
        reutrn;
    }
    console.log(v);//输出结果:3,4,5
})
//示例3:
arr.forEach(v=>{
    if(v>3){
        return;
    }
    console.log(v);//输出结果:0,1,2,3
})

上面前两个示例可以很直观的看出return并没有跳出循环,而示例3看似输出到3后就在停止循环了,其实输出到三后也并没有结束循环,只是结束了当前的回调函数!根据不同的例子,我的理解是:forEach其实是一个循环体,和一个函数体的结合,循环体包裹着函数体,所以return只是跳出了函数体,但是并没有跳出循环体。
查看MDN中Array.prototype.forEach()对forEach方法的解释:

forEach()方法对数组的每个元素执行一次提供的函数。

根据MDN中Polyfill板块中我们可以看到forEach()的实现原理callback在最内层,while是循环体包裹着callback!综上应该可以搞明白为啥forEach不能用return跳出循环啦!

if (!Array.prototype.forEach) {
  Array.prototype.forEach = function(callback, thisArg) {
    var T, k;
    if (this == null) {
      throw new TypeError(' this is null or not defined');
    }
    var O = Object(this);
    var len = O.length >>> 0;
    if (typeof callback !== "function") {
      throw new TypeError(callback + ' is not a function');
    }
    if (arguments.length > 1) {
      T = thisArg;
    }
    k = 0;
    while (k < len) {

      var kValue;
      if (k in O) {
        kValue = O[k];
        callback.call(T, kValue, k, O);
        //forEach原理看这!!!
      }
      k++;
    }
  };
}

搞明白了forEach无法跳出循环,那么当需要跳出循环的时候,我们应该怎么办呢?查看MDN,它为我们提供了下面的方法。

  • for循环
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()

我测试了上面的几种方法,还是发现了一些很有意思的情况~~~~

let arr=[0,1,2,3,4,5];
let result1=arr.some(v=>v<3);
let result2=arr.find(v=>v<3);
let result3=arr.every(v=>v<3);
console.log(`some:${result1},find:${result2},every:${result3}`);
//输出结果:some:true,find:0,every:false

every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。
find()是对数组中每一项运行给定函数,发现满足条件的函数即刻返回,不在执行后面函数。
some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。

arr.forEach(v=>{
        console.log(v);//输出结果:0,1,2,3,4,5
        if(v>2){
            return;
        }
    })
    console.log("---------------");
    arr.some(v=>{
        console.log(v);//输出结果:0,1,2,3
        if(v>2){
            return true;
        }
    })
    console.log("---------------");
    arr.find(v=>{
        console.log(v);//输出结果:0,1,2,3
        if(v>2){
            return true;
        }
        
    })
    console.log("---------------");
    arr.every(v=>{
        console.log(v);//输出结果:0
        if(v>2){
            return;
        }
    })
  //some(callback)和find(callback)方法中,如果callback函数体内的return~~~~后面不跟值,或者return后跟的是false都不能终止循环~~~~

如果用到循环遍历的情况还是要慎重选择!!!!

Image placeholder
candy
未设置
  29人点赞

没有讨论,发表一下自己的看法吧

推荐文章
Java迭代器(转)(iterator详解以及和for循环的区别)

课程推荐:Java开发工程师--学习猿地精品课程 迭代器是一种模式,它可以使得对于序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的。只要拿到这个对象,使用迭代

javascript遍历循环的3种方法

课程推荐:Java开发工程师--学习猿地--送7个上线商业项目 本文分享了js遍历循环的3种方法,代码加上文字解释说明,清晰明了,小编觉得文章不错,推荐给大家,希望你会喜欢。原文:https://se

一位从卖猪肉转行到前端开发小哥的自我救赎

一位曾经卖过猪肉的前端小哥自我救赎之路来自微信公众号:前端巅峰  的交流群真实采访花名:**郑伊健**一、你为什么要给自己取一个郑伊健的花名,有什么特殊含义特殊含义倒是没有,取这个花名,只是因为觉得郑

MESH无线究竟有多强? Linksys MR8300无线路由器评测

作为正儿八经的“北漂一族”,常年的蜗居生活让我对大房子的概念渐渐模糊,房东提供的无线路由器也能够满足日常的网络需求。但前段时间回了一趟河北老家才发现,家里的无线路由器已经远远不能够满足我的组网需求。信

程序员自我发展之路:从态度到方法

三周前,正值手头事情忙得不可开交之际,接到右总邀稿,要我谈谈程序员发展的几条出路。我思考再三,索性趁此机会干脆行文一篇,把自己多年来给团队的唠叨整理整理,也算不负他人之托。事先声明,本人并非专业的职业

阿里毕玄:从生物系学生,到技术团队 leader,他是如何完成自我蜕变的

©MSuzanneD.Williams编者按:新的技术层数不穷,困扰程序员的不仅有学不完的新技术,还有每个人在职业生涯中必然会面对的成长路线问题。这就像一个产品有了清晰的roadmap,下一步走的才会

PHP for和foreach的区别

推荐课程:PHP开发工程师--学习猿地精品在线课 首先,我们先准备两个用于遍历的数组: $arr1=array(1=>‘a‘,3=>22,5=>‘b‘,4=>‘c‘,8=>‘d‘); $arr2=ar

关于for丶foreach丶iterator 迭代器

课程推荐:Java开发工程师--学习猿地--送7个上线商业项目 1丶前言:我们在网上或者在讨论的时候往往会有这么一种说法:foreach也是迭代器的一类,底层实现的是迭代器。但是这种说法并不严谨,也可

别小瞧了 Linux,安卓、华为的自研系统,均源自 Linux!

众所周知,目前国内已有众多的国产系统,基本上均源自linux,以linux为基础进行二次开发。比如红旗linux、深度等等。但不知道为什么,一说起某系统是基于linux而来,很多网友就瞧不起,并且会觉

网络工程师眼中的自动化运维

本文从一名网工从业者的角度出发,探讨了在企业网运维过程中,网络工程师可以用什么样的工具让网络更加透明高效。上篇文章回顾:ApacheRanger——HadoopACL控制工具引言“网络就像wifi,没

5位女性程序员的自白:计算机不撒谎;女程序员的代码一样也很棒

谁说这个领域就是男性的天下偏见本身就是一种带标签的想法她们的世界里只信奉“computer never lies”她们认为代码漂亮比发型漂亮更重要她们到底是谁?谷悦是喜欢简单、纯粹工作的气质女神,八年

实操讲解:使用Keras中的自动编码器进行极端罕见事件分类

在这篇文章中,我们将学习如何实现用自动编码器来构建稀有事件分类器。我们将使用来自此处的真实稀有事件数据集。背景什么是极端罕见的事件?在一个罕见的问题中,我们有一个不平衡的数据集。意思是,我们得到的阳性

Python教程-循环结构

在Python中构造循环结构有两种做法,一种是for-in循环,一种是while循环。再程序中循环经常用到,比如在展示文章或者商品列表的时候,我们循环数据,并且转成html格式,我们需要对循环非常

可视化的JavaScript:事件循环

首先,事件循环是什么,为什么要理解它?JavaScript是单线程的:一次只能运行一个任务。通常这没什么大不了的,但现在想象一下我们正在运行一个需要30秒的任务。在这个任务中,我们要等待30秒,然后才

Elasticsearch 与传统关系型数据库的对比、倒排索引原理解析

Elasticsearch和传统关系型数据库的对比Elasticsearch中的概念与关系型数据库对比 RelationalDB Databases Tables Rows Columns 关系

表单元素无法继承CSS font字体设置详解

课程推荐:Java开发工程师--学习猿地精品课程 编者:CSS里面表单元素input,button,textarea,select等并不继承body的字体设置,它会使用系统或者浏览器自身的设置。通过这

PHP 内核:foreach 是如何工作的?

foreach是如何工作的? 首先声明,我知道foreach是什么,也知道怎么去用它。但这个问题关心的是,内核中foreach是如何运行的,我不想回答关于“如何使用foreach循环数组”的任何问题。

Java并发编程,深入理解ReentrantLock

ReentrantLock简介ReentrantLock重入锁, 是实现Lock接口的一个类 ,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次

10 分钟彻底理解 Redis 的持久化和主从复制

在这篇文章,我们继续有关Redis方面知识的学习,一起了解一下其中一个非常重要的内容:Redis的持久化机制。什么是Redis持久化?Redis作为一个键值对内存数据库(NoSQL),数据都存储在内存

如何理解react响应式

如何理解react响应式React中响应式原理1、开发者只需关注状态转移(数据),当状态发生变化,React框架会自动根据新的状态重新构建UI。2、React框架在接收到用户状态改变通知后,会根据当前

pymysql fetchone () , fetchall () , fetchmany ()

最近在用python操作mysql数据库时,碰到了下面这两个函数,标记一下: 1.定义 1.1fetchone(): 返回单个的元组,也就是一条记录(row),如果没有结果则返回None 1.2fet

理解 cookie、session、token、jwt

发展史 1、很久以前,Web基本上就是文档的浏览而已,既然是浏览,作为服务器,不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议,就是请求加响应,尤其是我不用记住是谁刚刚发了

零基础学测试 2 - 进一步理解 Laravel 的测试与 PHP Unit 的关系

细心的读者可以发现,上一讲中创建的用例继承的是PHPUnit的测试基类。

老司机带你深入理解 Laravel 之 Facade

前言 时间真的过的很快啊,今天都2019年12月2号了,准确的说,写这篇博客的时间是晚上21点40分,刚从公司加班回来,洗完澡就坐下来写这篇文章了,不知不觉除这篇博客外,我已经写了11篇了,要讲的东西

第 10 节:复合类型-5. 指针 -- 数组指针与指针数组的辅助理解

5数组指针与指针数组的辅助理解数组指针(也称行指针)定义int(*p)[n];\ ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p