[1,2,3].forEach(function(el) {if(el === 1) break;
});

如何使用JavaScript中新的forEach方法做到这一点? 我试过return;return false;breakbreak崩溃, return并没有做任何事情,而是继续迭代。


#1楼

您可以使用每种方法:

[1,2,3].every(function(el) {return !(el === 1);
});

ES6

[1,2,3].every( el => el !== 1 )

对于旧的浏览器支持,请使用:

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;};
}

更多细节在这里 。


#2楼

这只是我想出的解决问题的方法...我很确定它可以解决原始申请者所遇到的问题:

Array.prototype.each = function(callback){if(!callback) return false;for(var i=0; i<this.length; i++){if(callback(this[i], i) == false) break;}
};

然后,您可以使用以下命令进行调用:

var myarray = [1,2,3];
myarray.each(function(item, index){// do something with the item// if(item != somecondition) return false;
});

在回调函数内返回false将导致中断。 让我知道那是否实际上不起作用。


#3楼

简短的答案:为此使用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()回调函数之外更改某些var),这与for...break并没有太大区别。

因此,将.some().every()用作for...break循环替代方法并非没有副作用,这for...break并没有那么干净,这令人沮丧,因此这并不是更好。

您始终可以重写代码,这样就不需要for...break 。 您可以使用.filter()过滤数组,可以使用.slice()拆分数组,依此类推,然后将.forEach().map()用于数组的该部分。


#4楼

我想到的另一个概念是:

 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(); } }); 

#5楼

为此,我使用nullhack ,它尝试访问null属性,这是一个错误:

try {[1,2,3,4,5].forEach(function ( val, idx, arr ) {if ( val == 3 ) null.NULLBREAK;});
} catch (e) {// e <=> TypeError: null has no properties
}
//

#6楼

如果您不需要在迭代后访问数组,则可以通过将数组的长度设置为0来纾困。如果在迭代后仍然需要它,则可以使用slice克隆它。

[1,3,4,5,6,7,8,244,3,5,2].forEach(function (item, index, arr) {if (index === 3) arr.length = 0;
});

或使用克隆:

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;
});

与在代码中引发随机错误相比,这是一个更好的解决方案。


#7楼

没有内置的能力可以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; } 

JavaScript异常不是很漂亮。 传统for ,如果你真的需要循环可能更适合break里面。

使用Array#some

而是使用Array#some

 [1, 2, 3].some(function(el) { console.log(el); return el === 2; }); 

之所以true是因为some以数组顺序执行的回调一旦返回true ,就会使true短路,从而使其余的执行短路。

some ,其every相反(将在return false停止),以及forEach都是ECMAScript Fifth Edition方法,需要在缺少它们的浏览器上将它们添加到Array.prototype


#8楼

考虑使用jqueryeach方法,因为它允许在回调函数内返回false:

$.each(function(e, i) { if (i % 2) return false;console.log(e)
})

Lodash库还提供了可以与map / reduce / fold等链接的takeWhile方法:

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');
// => []

#9楼

在另一个站点上找到了此解决方案。 您可以在try / catch场景中包装forEach。

if(typeof StopIteration == "undefined") {StopIteration = new Error("StopIteration");
}try {[1,2,3].forEach(function(el){alert(el);if(el === 1) throw StopIteration;});
} catch(error) { if(error != StopIteration) throw error; }

此处有更多详细信息: http : //dean.edwards.name/weblog/2006/07/enum/


#10楼

var Book = {"Titles":[                          {"Book3" : "BULLETIN 3"}   ,{"Book1" : "BULLETIN 1"},{"Book2" : "BULLETIN 2"}
]}var findbystr = function(str) { var return_val;Book.Titles.forEach(function(data){ if(typeof data[str] != 'undefined'){return_val = data[str];} }, str) return return_val;
}book = findbystr('Book1');
console.log(book);

#11楼

使用array.prototype.every函数,该函数为您提供了打破循环的实用程序。 请参阅此处的示例Mozilla开发人员网络上的Javascript文档


#12楼

同意@bobince,赞成。

此外,仅供参考:

Prototype.js为此目的提供了一些东西:

<script type="text/javascript">$$('a').each(function(el, idx) {if ( /* break condition */ ) throw $break;// do something});
</script>

$break将由Prototype.js在内部捕获并处理,从而打破了“每个”周期,但不会产生外部错误。

有关详细信息,请参见Prototype.JS API 。

jQuery还有一种方法,只需在处理程序中返回false即可尽早中断循环:

<script type="text/javascript">jQuery('a').each( function(idx) {if ( /* break condition */ ) return false;// do something});
</script>

有关详细信息,请参见jQuery API 。


#13楼

现在,使用新的for循环在ECMAScript2015(aka ES6)中有一种更好的方法。 例如,此代码不会在数字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; } } 

从文档:

for ... infor ... of语句都会迭代某些内容。 它们之间的主要区别在于它们迭代的内容。 for ... in语句按原始插入顺序遍历对象的可枚举属性。 for ... of语句遍历可迭代对象定义要迭代的数据。

迭代中需要索引吗? 您可以使用Array.entries()

for (const [index, el] of arr.entries()) {if ( index === 5 ) break;
}

#14楼

不幸的是,在这种情况下,如果不使用forEach会更好。 而是使用常规的for循环,它现在将完全按照您的期望工作。

var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {if (array[i] === 1){break;}
}

#15楼

如果您想保留forEach语法,这是一种保持效率的方法(尽管不如常规的for循环好)。 立即检查一个变量,该变量知道您是否要退出循环。

本示例使用匿名函数围绕需要存储已完成信息的forEach创建函数作用域

 (function(){ var element = document.getElementById('printed-result'); var done = false; [1,2,3,4].forEach(function(item){ if(done){ return; } var text = document.createTextNode(item); element.appendChild(text); if (item === 2){ done = true; return; } }); })(); 
 <div id="printed-result"></div> 

我的两分钱。


#16楼

这不是最有效的,因为您仍然循环所有元素,但是我认为可能值得考虑一下非常简单的方法:

let keepGoing = true;
things.forEach( (thing) => {if (noMore) keepGoing = false;if (keepGoing) {// do things with thing}
});

#17楼

引用Array.prototype.forEach()的MDN文档 :

除了抛出异常外, 没有其他方法可以停止或中断 forEach()循环。 如果您需要这种行为,则.forEach()方法是错误的工具 ,请改用普通循环。 如果要为谓词测试数组元素并且需要布尔返回值,则可以改用every()some()

对于@bobince所建议的代码(在问题中),请改用Array.prototype.some() 。 它非常适合您的用例。

Array.prototype.some()对数组中存在的每个元素执行一次回调函数,直到找到一个回调返回真实值(转换为Boolean时变为true的Boolean )的元素为止。 如果找到了这样的元素, some()立即返回true。 否则, some()返回false。 仅对具有指定值的数组索引调用回调; 对于已删除或从未分配值的索引,不会调用它。


#18楼

您可以按照以下适用于我的代码进行操作:

 var     loopStop = false;
YOUR_ARRAY.forEach(function loop(){if(loopStop){ return; }if(condition){ loopStop = true; }
});

#19楼

从你的代码示例,它看起来像Array.prototype.find是你在找什么: Array.prototype.find()和Array.prototype.findIndex()

[1, 2, 3].find(function(el) {return el === 2;
}); // returns 2

#20楼

我知道这是不正确的方法。 这不是打破循环。 这是一个神态

 let result = true; [1, 2, 3].forEach(function(el) { if(result){ console.log(el); if (el === 2){ result = false; } } }); 

#21楼

我更喜欢for in

 var words = ['a', 'b', 'c']; var text = ''; for (x in words) { if (words[x] == 'b') continue; text += words[x]; } console.log(text); 

for in工作原理类似于forEach ,您可以在其中添加return到exit函数。 性能也更好。


#22楼

这是一个for循环,但是像forEach()一样在循环中维护对象引用,但是您可以将其拆分。

var arr = [1,2,3];
for (var i = 0, el; el = arr[i]; i++) {if(el === 1) break;
}

#23楼

如前所述,您不能破坏.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;}
}

输出:

item: { index: 0, val: 'one' }
item: { index: 1, val: 'two' }
break!

链接

  • Array.prototype.entries()
  • 迭代器和生成器
  • 销毁工作

#24楼

如果需要根据情况中断数组中元素的值(例如,中断条件不取决于在分配数组元素值后可能会更改的运行时变量),也可以使用组合slice()和indexOf()的形式如下。

如果您需要在forEach到达“ Apple”时休息一下,可以使用

var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var fruitsToLoop = fruits.slice(0, fruits.indexOf("Apple"));
// fruitsToLoop = Banana,Orange,LemonfruitsToLoop.forEach(function(el) {// no need to break
});

如W3Schools.com中所述,slice()方法将数组中选定的元素作为新的数组对象返回。 原始阵列将不会更改。

在JSFiddle中查看

希望它可以帮助某人。


#25楼

尝试“查找”:

var myCategories = [{category: "start", name: "Start", color: "#AC193D"},{category: "action", name: "Action", color: "#8C0095"},{category: "exit", name: "Exit", color: "#008A00"}
];function findCategory(category) {return myCategories.find(function(element) {return element.category === category;});
}console.log(findCategory("start"));
// output: { category: "start", name: "Start", color: "#AC193D" }

#26楼

另一种方法

        var wageType = types.filter(function(element){if(e.params.data.text == element.name){ return element;}});console.dir(wageType);

#27楼

如果您真的爱forEach我认为可以continue模仿。

arr.forEach(x=> {if(x>4) return;// some heavy code down below
});

但是,即使你崇拜forEach不使用黑客来模拟break -只要使用正规的for循环。 实际上,我想出了一个聪明的解决方案,但是请注意,由于它是mutate输入,因此效果不佳 。 如果您完全不介意更改提供的数据,则可以使用它,但是在大多数情况下,您都可以考虑。

arr.forEach(x=> {if (x>4) {arr.length=0; return;}// some heavy code might be here
});

#28楼

地图解决方案与OP示例非常相似。 关于性能, for循环是最快的,但是mapforEach一样简洁,而对于“没有太多的项目”,它不会有所作为。

[1,2,3].map(function(el) {if(el === 1) return
})

#29楼

以前,我的代码在下面

 this.state.itemsDataSource.forEach((item: any) => {if (!item.isByPass && (item.invoiceDate == null || item.invoiceNumber == 0)) {//BDialogHelper.show(this.state.context, 'Please enter inoice number or  date (' + item.itemName + ' )', DialogType.WARNING, DialogResponseStyle.OK);this.showStatusMessage('Please enter inoice number or  date (' + item.itemName + ' )');return false;}});

我已更改为以下内容,它已修复。

 for (var i = 0; i < this.state.itemsDataSource.length; i++) {var item = this.state.itemsDataSource[i];if (!item.isByPass && (item.invoiceDate == null || item.invoiceNumber == 0)) {BDialogHelper.show(this.state.context, 'Please enter inoice number or  date (' + item.itemName + ' )', DialogType.WARNING, DialogResponseStyle.OK);//this.showStatusMessage('Please enter inoice number or  date (' + item.itemName + ' )');return false;}}

#30楼

如果您想使用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;}}};}
})();

上面的代码将使您能够运行以下代码,而无需执行自己的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);
});

要记住的重要一件事是,这只会更新Array.prototype.forEach函数(如果已存在)。 如果尚不存在,则不会对其进行修改。

Array.forEach短路就像调用break相关推荐

  1. JavaScript Array forEach

    1.  js 数组循环遍历. 数组循环变量,最先想到的就是 for(var i=0;i<count;i++)这样的方式了. 除此之外,也可以使用较简便的forEach 方式 2.  forEac ...

  2. Array.ForEach的委托方法

    string[] strAarray = new string[] { "1", "2", "3", "4", &quo ...

  3. Array.forEach

    参见https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach 针对每个数组元 ...

  4. 前端防错以及好用小tips指南总结

    @前端防錯以及好用小tips指南總結 1.一般情況下我們接收到的都是對象格式,某些情況下,需要接到後端傳過來的奇怪的字符串格式的JSON,需要解析成對象,但是有時候他們傳過來的格式有問題,會報錯 解決 ...

  5. 前端工程师面试题详解(三)

     get 请求传参长度的误区 误区:我们经常说 get 请求参数的大小存在限制,而 post 请求的参数大小是无限制的.实际上 HTTP 协议从未规定 GET/POST 的请求长度限制是多少.对 g ...

  6. JavaScript最全面试题

    1.闭包 什么是闭包? MDN 的解释:闭包是函数和声明该函数的词法环境的组合. 按照我的理解就是:闭包 = 『函数』和『函数体内可访问的变量总和』 说白了就是函数嵌套函数,内部函数能够访问外部函数的 ...

  7. JavaScript 循环中调用异步函数的三种方法,及为什么 forEach 无法工作的分析

    JavaScript 循环中调用异步函数的三种方法,及为什么 forEach 无法工作的分析 业务分析 初版的问题 解决方案 传统的 for 循环 不使用 for 循环的解决方案 分析 forEach ...

  8. 面试官:有了 for 循环 为什么还要 forEach ?

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:juejin.cn/post/7018097650687803422 本质区别 for循环和forEach的语法区别 for循 ...

  9. JavaScript中 for、for in、for of、forEach等使用总结

    在JavaScript中,我们经常需要去循环迭代方法操作数组对象等,常见等循环方法有 for.for in.for of.forEach等. 1.for循环 for循环是最基础常见的一种循环,圆括号中 ...

最新文章

  1. 自动驾驶年度激辩:载货比载人更快,商业化应成为评价指标 | MEET2021
  2. 织梦gbk转utf8(数据库篇)
  3. python 3389爆破机
  4. FTP服务(3)实现基于文件验证的vsftpd虚拟用户
  5. SpringMVC的请求-文件上传-单文件上传的代码实现2
  6. 《图解 HTTP》读书笔记(未完待续)
  7. python的Web编程
  8. WinCE中的RAM-Based Registry与HIVE-Based Registry
  9. latex插入图片之后出现大段空白,并且紧随其后的文字如同被覆盖一般不见了
  10. org.apache.http.NoHttpResponseException
  11. mysql哨兵机制_Sentinel:万字详解微服务的哨兵机制,我跪了
  12. 【转】python模块分析之collections(六)
  13. 【DA】单侧T检验p值与双侧T检验p值的关系
  14. Adaptive icon 一 :理解 Android 的「自适应图标」
  15. 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
  16. 科幻电影里的机器人假肢已经照进现实
  17. 深度学习推理框架调研总结
  18. java.net cidr接口_【算法】CIDR集合的算法
  19. Flutter 元宇宙开发教程之通过 Flutter 和增强现实实现 Metaverse
  20. 《基础知识》提示学习的基本知识

热门文章

  1. 算法--------俄罗斯套娃信封问题(Java版本)
  2. Retrofit get post query filed FiledMap
  3. 第十六周程序阅读(8)
  4. 第八周项目四-角色有多样武器
  5. listview的divider边距
  6. python 代理上网_用Python编写脚本使IE实现代理上网的教程
  7. python商业爬虫教程_廖雪峰老师的Python商业爬虫课程 Python网络爬虫实战教程 体会不一样的Python爬虫课程...
  8. windows清理_Windows系统高级清理工具,实力吊打360!
  9. Android之利用回调函数onCreateDialog实现加载对话框
  10. 【常见问题】Can not perform this action after onSaveInstanceState