起因
在可视化数据的大环境下,前端的页面驱动基本是基于,每个函数或多或少都会做一些数据上的判断,这时候就会用到循环的跳出。
场景
由于后台反馈以及前端反馈的数据都是list格式的数据,我先用的是forEach,forEach运用的时候可以更好的便利出item,当然也是习惯性用forEach。但是在forEach中遍历的时候做的判断是不支持弹出整个函数,而for循环可以。
for循环试一下return
- 想当然的用return啊,结果:呵呵!
for (let i = 0; i < 3; i++) { console.log(110); if (i === 1) { return }}复制代码
这段代码,我想当然的认为:i===1时遇到return跳出循环,只会打印两次110,但是当我在控制台按下回车时,啪啪啪打脸啊,脸都打肿了,我还不知道为啥!直接报:Illegal return statement
return语句就是用于指定函数返回的值。return语句只能出现在函数体内,出现在代码中的其他任何地方都会造成语法错误! 地方都会造成语法错误!
竟然还有这种限制,为何我以前怎么没发觉,仔细看了下以前的代码,貌似,我的for都是写在函数内的,所以没报错。。。
当然,为了保险点,又去MDN看了下return,果不其然,MDN上抬头就是一句:return语句终止函数的执行,并返回一个指定的值给函数调用者。
更保险的可以看。规范里面也说了返回语句使函数停止执行,并将值返回给调用方。
-
既然return不是为for服务的,那么该怎么去跳出for循环呢? 稍微有基础的同学们都会想到break和continute。
在这里我先给ECMA规范里的。
MDN上关于break的说明:break 语句中止当前循环,switch语句或label 语句,并把程序控制流转到紧接着被中止语句后面的语句。break可不仅仅是跳出循环这么简单哦~
for (let j = 0; j < 3; j++) { console.log(112); if (j === 1) { break; }}复制代码
-
continue
结合代码看下continue的功能,其实就是break;continue。
for (let j = 0; j < 3; j++) { if (j === 1) { continue; } console.log(j); }复制代码
为什么不能跳出forEach?
- 先用break和continue分别测试一波,看看问题是否成立。
arr.forEach(function(item){ if (item === 2) { break; } console.log(item);})arr.forEach(function(item){ console.log(110) if (item === 2) { continue; } console.log(item);})复制代码
控制台均报语法错误!!!尤其continue提示没有包含在一个迭代语句中!!!
去看看MDN上面的,其中明确提到:
没有办法中止或者跳出 forEach 循环,除了抛出一个异常。如果你需要这样,使用
forEach()
方法是错误的,你可以用一个简单的循环作为替代。如果您正在测试一个数组里的元素是否符合某条件,且需要返回一个布尔值,那么可使用Array.every
或Array.some
。如果可用,新方法find()
或者findIndex()
也可被用于真值测试的提早终止。
同时,去看看规范里的forEach。貌似没有说为什么。那么怎么办呢?
回顾continue
报错提示,需要被包含在迭代语句内,难道forEach不是迭代语句吗?它作用不就是遍历 吗?抱着这些问题,我在规范的目录里走马观花的查看,突然发现这个Iteration Statements,这个目录名不就是continue要求的迭代语句嘛。
我点了下去,大致看了下,果然没有forEach
,而且map
,filter
等都没有。。。
我有尝试去看v8关于forEach的源码实现,可惜并没有找到。。。
不过这里可以提供一个仿map方法的_map,本质上是一样的,只是侧重点不同,有些实现不同。我们平常这样使用:arr.forEach(function(){})
,我们都是在function(){}
中去做我们需要的操作,但是,forEach本质上就是一个函数,而我们写的函数其实是传递给它调用的回调函数!!!
所以,当我在回调函数内写了return,即使符合条件也只是跳出回调函数而已,并没有跳出调用它的forEach!
demo
function a(i) { console.log(i); if(i === 1) { return }}function b(arr) { for(var i = 0; i < arr.length; i++) { a(i) }}var arr = [1,2,3,4,5]b(arr)复制代码
总结下
由这一个小问题挖掘出这么多小知识也是不错的,有利于夯实js基础。以后遇到类似的业务场景时,可以更好利用出来。