Sco*_*ach 1429 javascript arrays
[1,2,3].forEach(function(el) {
if(el === 1) break;
});
Run Code Online (Sandbox Code Playgroud)
如何forEach在JavaScript中使用新方法执行此操作?我试过了return;,return false;而且break.break崩溃,return除了继续迭代之外什么都不做.
bob*_*nce 1962
有没有内置的能力break的forEach.要中断执行,你必须抛出某种异常.例如.
var BreakException = {};
try {
[1, 2, 3].forEach(function(el) {
console.log(el);
if (el === 2) throw BreakException;
});
} catch (e) {
if (e !== BreakException) throw e;
}Run Code Online (Sandbox Code Playgroud)
JavaScript异常并不是非常漂亮.for如果你真的需要break在它里面,传统的循环可能更合适.
Array#some相反,使用Array#some:
[1, 2, 3].some(function(el) {
console.log(el);
return el === 2;
});Run Code Online (Sandbox Code Playgroud)
这是有效的,因为只要以数组顺序执行的任何回调some返回true,就会立即返回true,从而使其余的执行短路.
some,它的逆every(它将停止在a return false),并且forEach都是ECMAScript第五版方法,需要将它们添加到Array.prototype它们缺失的浏览器上.
can*_*nac 374
现在有一种更好的方法可以在ECMAScript2015(又名ES6)中使用new for for循环来完成这项工作.例如,此代码不会在数字5之后打印数组元素:
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (let el of arr) {
console.log(el);
if (el === 5) {
break;
}
}Run Code Online (Sandbox Code Playgroud)
来自文档:
无论对于...在和对...的语句迭代的东西.它们之间的主要区别在于它们迭代的内容.在为...在声明中遍历对象的枚举的属性,在原来的插入顺序.在对...的语句迭代数据迭代的对象定义要遍历.
在迭代中需要索引吗?您可以使用Array.entries():
for (const [index, el] of arr.entries()) {
if ( index === 5 ) break;
}
Run Code Online (Sandbox Code Playgroud)
Val*_*ich 192
您可以使用每种方法:
[1,2,3].every(function(el) {
return !(el === 1);
});
Run Code Online (Sandbox Code Playgroud)
ES6
[1,2,3].every( el => el !== 1 )
Run Code Online (Sandbox Code Playgroud)
对于旧浏览器支持使用:
if (!Array.prototype.every)
{
Array.prototype.every = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this &&
!fun.call(thisp, this[i], i, this))
return false;
}
return true;
};
}
Run Code Online (Sandbox Code Playgroud)
这里有更多细节.
Rah*_*sai 69
引用MDN文档Array.prototype.forEach():
有没有办法阻止或打破一个
forEach()比抛出异常等循环.如果您需要这样的行为,该.forEach()方法是错误的工具,而是使用普通循环.如果要测试谓词的数组元素并需要布尔返回值,则可以使用every()或some()替代.
对于你的代码(在问题中),正如@bobince建议的那样,请Array.prototype.some()改用.它非常适合您的用例.
Array.prototype.some()对数组中存在的每个元素执行一次回调函数,直到找到一个回调返回truthy值的值(转换为a时变为true的值Boolean).如果找到这样的元素,则some()立即返回true.否则,some()返回false.仅为已分配值的数组的索引调用回调; 对于已删除的索引或从未分配过值的索引,不会调用它.
Wes*_*ger 66
不幸的是,在这种情况下,如果你不使用它会好得多forEach.而是使用常规for循环,它现在将完全按照您的预期工作.
var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {
if (array[i] === 1){
break;
}
}
Run Code Online (Sandbox Code Playgroud)
vit*_*ore 25
考虑使用jquery's each方法,因为它允许在回调函数内返回false:
$.each(function(e, i) {
if (i % 2) return false;
console.log(e)
})
Run Code Online (Sandbox Code Playgroud)
Lodash库还提供takeWhile了可以与map/reduce/fold等链接的方法:
var users = [
{ 'user': 'barney', 'active': false },
{ 'user': 'fred', 'active': false },
{ 'user': 'pebbles', 'active': true }
];
_.takeWhile(users, function(o) { return !o.active; });
// => objects for ['barney', 'fred']
// The `_.matches` iteratee shorthand.
_.takeWhile(users, { 'user': 'barney', 'active': false });
// => objects for ['barney']
// The `_.matchesProperty` iteratee shorthand.
_.takeWhile(users, ['active', false]);
// => objects for ['barney', 'fred']
// The `_.property` iteratee shorthand.
_.takeWhile(users, 'active');
// => []
Run Code Online (Sandbox Code Playgroud)
Oli*_*ran 19
从您的代码示例中,它看起来像Array.prototype.find您正在寻找的:Array.prototype.find()和Array.prototype.findIndex()
[1, 2, 3].find(function(el) {
return el === 2;
}); // returns 2
Run Code Online (Sandbox Code Playgroud)
Chr*_*est 14
如果您想使用Dean Edward的建议并抛出StopIteration错误以突破循环而不必捕获错误,您可以使用以下函数(最初来自此处):
// Use a closure to prevent the global namespace from be polluted.
(function() {
// Define StopIteration as part of the global scope if it
// isn't already defined.
if(typeof StopIteration == "undefined") {
StopIteration = new Error("StopIteration");
}
// The original version of Array.prototype.forEach.
var oldForEach = Array.prototype.forEach;
// If forEach actually exists, define forEach so you can
// break out of it by throwing StopIteration. Allow
// other errors will be thrown as normal.
if(oldForEach) {
Array.prototype.forEach = function() {
try {
oldForEach.apply(this, [].slice.call(arguments, 0));
}
catch(e) {
if(e !== StopIteration) {
throw e;
}
}
};
}
})();
Run Code Online (Sandbox Code Playgroud)
上面的代码将使您能够运行以下代码而无需执行自己的try-catch子句:
// Show the contents until you get to "2".
[0,1,2,3,4].forEach(function(val) {
if(val == 2)
throw StopIteration;
alert(val);
});
Run Code Online (Sandbox Code Playgroud)
需要记住的一件重要事情是,只有已经存在的Array.prototype.forEach函数才会更新.如果它不存在,则不会修改它.
简短回答:for...break用于此或更改您的代码以避免破坏forEach.不要使用.some()或.every()模仿for...break.重写代码以避免for...break循环或使用for...break.每次你使用这些方法作为for...break替代,上帝杀死小猫.
答案很长:
.some()并且.every()都返回boolean值,.some()返回true是否有针对任何元素传递函数返回true,每返回false如果有任何元素,其传递函数返回false.这就是这个功能的意思.使用函数来表示它们并不意味着比使用表格而不是CSS更糟糕,因为它会让所有读取代码的人感到沮丧.
此外,使用这些方法作为for...break替代方法的唯一可能方法是产生副作用(在.some()回调函数之外更改一些变量),这与之没有太大区别for...break.
因此,使用.some()或.every()作为for...break循环替代品并非没有副作用,这不是更清洁for...break,这是令人沮丧的,所以这不是更好.
您始终可以重写代码,以便不需要for...break.你可以使用过滤数组.filter(),你可以使用.slice()等分割数组,然后使用.forEach()或.map()用于数组的那部分.
小智 7
这只是我想出来的解决问题的方法......我很确定它解决了原始提问者遇到的问题:
Array.prototype.each = function(callback){
if(!callback) return false;
for(var i=0; i<this.length; i++){
if(callback(this[i], i) == false) break;
}
};
Run Code Online (Sandbox Code Playgroud)
然后你可以使用以下方法调用它:
var myarray = [1,2,3];
myarray.each(function(item, index){
// do something with the item
// if(item != somecondition) return false;
});
Run Code Online (Sandbox Code Playgroud)
在回调函数中返回 false 将导致中断。如果这实际上不起作用,请告诉我。
我提出的另一个概念:
function forEach(array, cb) {
var shouldBreak;
function _break() { shouldBreak = true; }
for (var i = 0, bound = array.length; i < bound; ++i) {
if (shouldBreak) { break; }
cb(array[i], i, array, _break);
}
}
// Usage
forEach(['a','b','c','d','e','f'], function (char, i, array, _break) {
console.log(i, char);
if (i === 2) { _break(); }
});Run Code Online (Sandbox Code Playgroud)
如前所述,你不能打破.forEach().
这是一种使用 ES6 迭代器进行 foreach 的更现代的方法。允许您在迭代时直接访问index/ value。
const array = ['one', 'two', 'three'];
for (const [index, val] of array.entries()) {
console.log('item:', { index, val });
if (index === 1) {
console.log('break!');
break;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
item: { index: 0, val: 'one' }
item: { index: 1, val: 'two' }
break!
Run Code Online (Sandbox Code Playgroud)
如果您不需要在迭代后访问您的数组,您可以通过将数组的长度设置为 0 来退出。如果您在迭代后仍然需要它,您可以使用 slice..
[1,3,4,5,6,7,8,244,3,5,2].forEach(function (item, index, arr) {
if (index === 3) arr.length = 0;
});
Run Code Online (Sandbox Code Playgroud)
或者使用克隆:
var x = [1,3,4,5,6,7,8,244,3,5,2];
x.slice().forEach(function (item, index, arr) {
if (index === 3) arr.length = 0;
});
Run Code Online (Sandbox Code Playgroud)
这是一个更好的解决方案,然后在您的代码中抛出随机错误。