起因
在視覺化資料的大環境下,前端的頁面驅動基本是基於,每個函式或多或少都會做一些資料上的判斷,這時候就會用到迴圈的跳出。
場景
由於後臺反饋以及前端反饋的資料都是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語句終止函式的執行,並返回一個指定的值給函式呼叫者。
更保險的可以看ECMAScript® 2015 Language Specification return。規範裡面也說了返回語句使函式停止執行,並將值返回給呼叫方。
-
既然return不是為for服務的,那麼該怎麼去跳出for迴圈呢? 稍微有基礎的同學們都會想到break和continute。
在這裡我先給ECMA規範裡的for。
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 迴圈,除了丟擲一個異常。如果你需要這樣,使用
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基礎。以後遇到類似的業務場景時,可以更好利用出來。