眾所皆知,在 JavaScript 中的 Array 有一個 forEach() 方法很好用(而且 IE 9 以上有支援),大部分的使用情境都可以用來取代傳統的 for 語法,但難免會有需要 continue 或 break 的場景,continue;
及 break;
在 forEach() 方法中是不會有作用的,我們需要換個方式來做。
首先,我們先看一下 forEach() 方法 Polyfill 的原始碼,先了解整個 forEach() 方法的實作邏輯,從這裡面我們可以知道,forEach() 方法的內部實際上是跑一個 while 迴圈,而不是 for 迴圈。
continue
在了解了整個 forEach() 方法的實作邏輯之後,如果我們要實現 continue; 的效果,其實只要在 callback function 裡面加上 return 即可。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array.forEach(function (item, index) {
if (item >= 2 && item <= 7) {
return;
}
console.log(item);
});
// 印出:
// 1
// 8
// 9
break
但是要實現 break; 就沒那麼容易了,這等同於是要在 while 迴圈中 break;,而我們又只能在 callback function 裡面下手,所以只得繞道而行,底下提供三種方式給大家參考。
Array.prototype.splice()
第一種方法我們要借助 Array.prototype.splice() 方法,splice() 方法有個特性,就是它會去異動到記憶體中實體的陣列,所以我們只要在需要 break 的地方,將陣列中後面的元素移除掉,讓 while 迴圈取不到元素,就達到了 break; 的效果。
但是用 splice() 要非常小心,所有參考到這個實體陣列的變數也都會受到影響,所以我們需要建立另一個擁有相同元素的陣列來執行 forEach(),在 JavaScript 中方法有很多,而我選用 Array.from() 來幫我建立相同元素的陣列。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
Array.from(array).forEach(function (item, index, arr) {
if (item === 4) {
arr.splice(index, arr.length - index);
return;
}
console.log(item);
});
// 印出:
// 1
// 2
// 3
throw exception
第二種方法比較暴力一點,直接在需要 break 的地方吐 Exception,讓程式強制中斷,也能達到 break; 的效果。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
try {
array.forEach(function (item, index) {
if (item === 4) {
throw {};
}
console.log(item);
});
} catch { }
// 印出:
// 1
// 2
// 3
可以把它做成一個 tryForEach()
方法,放在 Array.prototype 裡面。
if (!Array.prototype.tryForEach) {
Array.prototype.tryForEach = function (callback, thisArg) {
try {
this.forEach(callback, thisArg);
} catch { }
}
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array.tryForEach(function (item, index) {
if (item === 4) {
throw {};
}
console.log(item);
});
// 印出:
// 1
// 2
// 3
空轉
第三種方法是讓 while 迴圈空轉,我們只要加一個 break flag
,在需要 break 的地方將 break flag 標記為 true,此後的循環全部 return 都不執行,以此達到 break; 的效果。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array.forEach(function (item, index) {
if (this.breakFlag === true) return;
if (item === 4) {
this.breakFlag = true;
return;
}
console.log(item);
});
// 印出:
// 1
// 2
// 3
或許可以用 some()
上面那三種在 forEach() 實現 break; 的方法,就提供給有需要朋友參考,我們來聊聊另外一個方法 - Array.prototype.some(),它相當於 C# 中的 Any(),雖然語意上它不是用來實現 break; 效果的,但是我個人認為,如果我們不想用 for 語法又有 break 的需求,用 some() 是挺適合的。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array.some(function (item, index) {
if (item === 4) {
return true;
}
console.log(item);
});
// 印出:
// 1
// 2
// 3
最後,如果我們對 JavaScript 裡面的 for 語法還停留在 for (var i = 0; i < length; i++) { }
這個印象的朋友,其實 JavaScript 還有兩個 for 語法:for...in 及 for...of(IE no support),也提供給各位朋友參考。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var index in array) {
if (array.hasOwnProperty(index)) {
var item = array[index];
if (item === 4) {
break;
}
console.log(item);
}
}
// IE no support
for (var item of array) {
if (item === 4) {
break;
}
console.log(item);
}
// 皆印出:
// 1
// 2
// 3