本文共 10721 字,大约阅读时间需要 35 分钟。
[1,2,3].forEach(function(el) { if(el === 1) break;});
如何使用中新的forEach
方法做到这一点? 我试过return;
, return false;
和break
。 break
崩溃, return
并没有做任何事情,而是继续迭代。
您可以使用方法:
[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; };}
更多细节 。
这只是我想出的解决问题的方法...我很确定它可以解决原始申请者所遇到的问题:
Array.prototype.each = function(callback){ if(!callback) return false; for(var i=0; i
然后,您可以使用以下命令进行调用:
var myarray = [1,2,3];myarray.each(function(item, index){ // do something with the item // if(item != somecondition) return false; });
在回调函数内返回false将导致中断。 让我知道那是否实际上不起作用。
简短的答案:为此使用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()
用于数组的该部分。
我想到的另一个概念是:
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(); } });
为此,我使用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}//
如果您不需要在迭代后访问数组,则可以通过将数组的长度设置为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;});
与在代码中引发随机错误相比,这是一个更好的解决方案。
没有内置的能力可以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
里面。
而是使用 :
[1, 2, 3].some(function(el) { console.log(el); return el === 2; });
之所以true
是因为some
以数组顺序执行的回调一旦返回true
,就会使true
短路,从而使其余的执行短路。
some
,其相反(将在return false
停止),以及forEach
都是ECMAScript Fifth Edition方法,需要在缺少它们的浏览器上将它们添加到Array.prototype
。
考虑使用jquery
的each
方法,因为它允许在回调函数内返回false:
$.each(function(e, i) { if (i % 2) return false; console.log(e)})
Lodash库还提供了可以与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');// => []
在另一个站点上找到了此解决方案。 您可以在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; }
此处有更多详细信息: :
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);
使用array.prototype.every
函数,该函数为您提供了打破循环的实用程序。 请参阅此处的示例
同意@bobince,赞成。
此外,仅供参考:
Prototype.js为此目的提供了一些东西:
$break
将由Prototype.js在内部捕获并处理,从而打破了“每个”周期,但不会产生外部错误。
有关详细信息,请参见 。
jQuery还有一种方法,只需在处理程序中返回false即可尽早中断循环:
有关详细信息,请参见 。
现在,使用新的在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 ... in和for ... of语句都会迭代某些内容。 它们之间的主要区别在于它们迭代的内容。 for ... in语句按原始插入顺序遍历对象的可枚举属性。 for ... of语句遍历可迭代对象定义要迭代的数据。
迭代中需要索引吗? 您可以使用 :
for (const [index, el] of arr.entries()) { if ( index === 5 ) break;}
不幸的是,在这种情况下,如果不使用forEach
会更好。 而是使用常规的for
循环,它现在将完全按照您的期望工作。
var array = [1, 2, 3];for (var i = 0; i < array.length; i++) { if (array[i] === 1){ break; }}
如果您想保留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; } }); })();
我的两分钱。
这不是最有效的,因为您仍然循环所有元素,但是我认为可能值得考虑一下非常简单的方法:
let keepGoing = true;things.forEach( (thing) => { if (noMore) keepGoing = false; if (keepGoing) { // do things with thing }});
引用的 :
除了抛出异常外, 没有其他方法可以停止或中断
forEach()
循环。 如果您需要这种行为,则.forEach()
方法是错误的工具 ,请改用普通循环。 如果要为谓词测试数组元素并且需要布尔返回值,则可以改用或 。
对于@bobince所建议的代码(在问题中),请改用 。 它非常适合您的用例。
Array.prototype.some()
对数组中存在的每个元素执行一次回调函数,直到找到一个回调返回真实值(转换为Boolean
时变为true的Boolean
)的元素为止。 如果找到了这样的元素,some()
立即返回true。 否则,some()
返回false。 仅对具有指定值的数组索引调用回调; 对于已删除或从未分配值的索引,不会调用它。
您可以按照以下适用于我的代码进行操作:
var loopStop = false;YOUR_ARRAY.forEach(function loop(){ if(loopStop){ return; } if(condition){ loopStop = true; }});
从你的代码示例,它看起来像Array.prototype.find
是你在找什么: 和
[1, 2, 3].find(function(el) { return el === 2;}); // returns 2
我知道这是不正确的方法。 这不是打破循环。 这是一个神态
let result = true; [1, 2, 3].forEach(function(el) { if(result){ console.log(el); if (el === 2){ result = false; } } });
我更喜欢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函数。 性能也更好。
这是一个for循环,但是像forEach()一样在循环中维护对象引用,但是您可以将其拆分。
var arr = [1,2,3];for (var i = 0, el; el = arr[i]; i++) { if(el === 1) break;}
如前所述,您不能破坏.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!
如果需要根据情况中断数组中元素的值(例如,中断条件不取决于在分配数组元素值后可能会更改的运行时变量),也可以使用组合和形式如下。
如果您需要在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});
如所述,slice()方法将数组中选定的元素作为新的数组对象返回。 原始阵列将不会更改。
在中
希望它可以帮助某人。
尝试“查找”:
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" }
另一种方法
var wageType = types.filter(function(element){ if(e.params.data.text == element.name){ return element; } }); console.dir(wageType);
如果您真的爱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});
地图解决方案与OP示例非常相似。 关于性能, for循环是最快的,但是map和forEach一样简洁,而对于“没有太多的项目”,它不会有所作为。
[1,2,3].map(function(el) { if(el === 1) return})
以前,我的代码在下面
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; } }
如果您想使用并抛出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函数(如果已存在)。 如果尚不存在,则不会对其进行修改。
转载地址:http://ebdnb.baihongyu.com/