Javascript 短路Array.forEach类呼叫中断

Javascript 短路Array.forEach类呼叫中断,javascript,arrays,foreach,Javascript,Arrays,Foreach,如何在JavaScript中使用新的forEach方法实现这一点?我试过return,返回false和中断中断崩溃并且返回除了继续迭代之外什么都不做。在forEach中没有内置的中断功能。要中断执行,您必须抛出某种异常。例如 var BreakException={}; 试一试{ [1,2,3].forEach(函数(el){ 控制台日志(el); 如果(el==2)抛出BreakException; }); }捕获(e){ 如果(e!==BreakException)抛出e; }考虑使用jq

如何在JavaScript中使用新的
forEach
方法实现这一点?我试过
return
返回false
中断
<代码>中断
崩溃并且
返回
除了继续迭代之外什么都不做。

forEach
中没有内置的
中断
功能。要中断执行,您必须抛出某种异常。例如

var BreakException={};
试一试{
[1,2,3].forEach(函数(el){
控制台日志(el);
如果(el==2)抛出BreakException;
});
}捕获(e){
如果(e!==BreakException)抛出e;

}
考虑使用
jquery
每个方法,因为它允许在回调函数中返回false:

[1,2,3].forEach(function(el) {
    if(el === 1) break;
});
Lodash库还提供了可以与map/reduce/fold等链接的方法:

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

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

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');
// => []
此处有更多详细信息:

如果您希望使用并抛出StopIteration错误来中断循环,而不必捕获错误,则可以使用以下函数():

上述代码将使您能够运行以下代码,而无需执行自己的try-catch子句:

// 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;
        }
      }
    };
  }
})();
需要记住的一点是,这只会更新Array.prototype.forEach函数(如果它已经存在)。如果它不存在,它将不会修改它。

您可以使用以下方法:

ES6

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

[1,2,3].every( el => el !== 1 )
if(!Array.prototype.every)
{
Array.prototype.every=函数(fun/*,thisp*/)
{
var len=此长度;
如果(乐趣的类型!=“功能”)
抛出新的TypeError();
var thisp=参数[1];
对于(变量i=0;i

更多细节。

这只是我想出的解决问题的办法。。。我很确定它解决了最初询问者的问题:

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

在回调函数中返回false将导致中断。如果这实际上不起作用,请告诉我。

简短回答:使用
来…中断
,或者更改您的代码以避免中断每个
。不要使用
.some()
.every()
来模拟
的…中断
。重写代码以避免
for…break
循环,或使用
for…break
。每次你使用这些方法,比如说,
for…break
alternative上帝会杀死小猫

长答覆:

.some()
.every()
都返回
布尔值,
.some()
返回
true
如果有传递函数返回
true
的元素,则每个元素返回
false
如果有传递函数返回
false
的元素。这就是函数的含义。将函数用于它们并不意味着的内容比将表用于布局而不是CSS要糟糕得多,因为这会让所有阅读您代码的人都感到沮丧

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;
});
另外,将这些方法用作
for…break
替代方法的唯一可能方法是产生副作用(在
.some()
回调函数之外更改一些变量),这与
for…break
没有太大区别

因此,使用
.some()
.every()
作为
for…break
循环替代方案并不是没有副作用的,这比
for…break
要干净得多,这是令人沮丧的,所以也不是更好


您可以随时重写代码,这样就不需要在
中使用…break
。您可以使用
.filter()
过滤数组,您可以使用
.slice()
等拆分数组,然后对数组的该部分使用
.forEach()
.map()

我提出的另一个概念:

函数forEach(数组,cb){ var应该中断; 函数_break(){shouldBreak=true;} 对于(变量i=0,界限=array.length;i我使用nullhack就是为了这个目的,它试图访问
null
的属性,这是一个错误:

var myarray = [1,2,3];
myarray.each(function(item, index){
    // do something with the item
    // if(item != somecondition) return false; 
});
试试看{
[1,2,3,4,5]
弗雷奇先生(
功能(val、idx、arr){
如果(val==3)null.NULLBREAK;
}
);
}捕获(e){
//e TypeError:null没有属性
}
//

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

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

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

这是一个比在代码中抛出随机错误更好的解决方案。

使用
数组.prototype.each
函数,它为您提供了打破循环的实用工具。参见此处示例

同意@bobince,向上投票

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;
});
此外,供参考:

Prototype.js为此提供了一些功能:

const Book = {"Titles":[                          
    {"Book3" : "BULLETIN 3"},
    {"Book1" : "BULLETIN 1"},
    {"Book2" : "BULLETIN 2"}    
]}

const findbystr = function(str) { 
    Book.Titles.forEach(function(data) { 
        if (typeof data[str] != 'undefined') {
            return data[str];
        } 
    }, str) 
}

book = findbystr('Book1');

console.log(book);

有关详细信息,请参阅。

现在,在ECMAScript 2015(又称ES6)中,使用新的。例如,此代码不打印数字5之后的数组元素:

让arr=[0,1,2,3,4,5,6,7,8,9,10];
对于(让el代表arr){
控制台日志(el);
如果(el==5){
打破
}

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

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

  });
</script>
var数组=[1,2,3];
对于(var i=0;i
如果您想保持
forEach
语法,这是一种保持其效率的方法(尽管不如常规for循环好)。立即检查一个变量,该变量知道
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;
});
const Book = {"Titles":[                          
    {"Book3" : "BULLETIN 3"},
    {"Book1" : "BULLETIN 1"},
    {"Book2" : "BULLETIN 2"}    
]}

const findbystr = function(str) { 
    Book.Titles.forEach(function(data) { 
        if (typeof data[str] != 'undefined') {
            return data[str];
        } 
    }, str) 
}

book = findbystr('Book1');

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

  });
</script>
var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {
  if (array[i] === 1){
    break;
  }
}
let keepGoing = true;
things.forEach( (thing) => {
  if (noMore) keepGoing = false;
  if (keepGoing) {
     // do things with thing
  }
});
 var     loopStop = false;
YOUR_ARRAY.forEach(function loop(){
    if(loopStop){ return; }
    if(condition){ loopStop = true; }
});
[1, 2, 3].find(function(el) {
    return el === 2;
}); // returns 2
var arr = [1,2,3];
for (var i = 0, el; el = arr[i]; i++) {
    if(el === 1) break;
}
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!
var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var fruitsToLoop = fruits.slice(0, fruits.indexOf("Apple"));
// fruitsToLoop = Banana,Orange,Lemon

fruitsToLoop.forEach(function(el) {
    // no need to break
});
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);
export type LoopControlOp = "break" | "continue" | ["return", any];
export type LoopFunc<T> = (value: T, index: number, array: T[])=>LoopControlOp;

Array.prototype.ForEach = function ForEach<T>(this: T[], func: LoopFunc<T>) {
    for (let i = 0; i < this.length; i++) {
        const controlOp = func(this[i], i, this);
        if (controlOp == "break") break;
        if (controlOp == "continue") continue;
        if (controlOp instanceof Array) return controlOp[1];
    }
};

// this variant lets you use async/await in the loop-func, with the loop "awaiting" for each entry
Array.prototype.ForEachAsync = async function ForEachAsync<T>(this: T[], func: LoopFunc<T>) {
    for (let i = 0; i < this.length; i++) {
        const controlOp = await func(this[i], i, this);
        if (controlOp == "break") break;
        if (controlOp == "continue") continue;
        if (controlOp instanceof Array) return controlOp[1];
    }
};
function GetCoffee() {
    const cancelReason = peopleOnStreet.ForEach((person, index)=> {
        if (index == 0) return "continue";
        if (person.type == "friend") return "break";
        if (person.type == "boss") return ["return", "nevermind"];
    });
    if (cancelReason) console.log("Coffee canceled because: " + cancelReason);
}
traverseTree(doc): Promise<any> {
  return new Promise<any>((resolve, reject) => {
    this.gridOptions.api.forEachNode((node, index) => {
    //the above function is the one I want to short circuit.
      if(node.data.id === doc.id) {
        return resolve(node);
      }
    });
  });
}
this.traverseTree(doc).then((result) => {
   this.doSomething(result);
});