JS เชิงมุมทำลาย ForEach


256

ฉันมีวง foreach เชิงมุมและฉันต้องการที่จะแยกออกจากวงถ้าฉันตรงกับค่า รหัสต่อไปนี้ใช้งานไม่ได้

angular.forEach([0,1,2], function(count){
  if(count == 1){
    break;
  }
});

ฉันจะได้รับสิ่งนี้ได้อย่างไร


1
ฉันไม่เข้าใจว่าทำไมคุณไม่เพียงแค่หาค่าแทนที่จะไปวนซ้ำ บางทีตัวอย่างที่คุณให้ไม่ได้บอกเรื่องราวทั้งหมด แต่ฉันอยากทำในสิ่งที่ @Aman พูดไว้ด้านล่าง ทำไมต้องเข้าสู่วงตามที่ระบุไว้ด้านล่างและเรียกใช้การตรวจสอบทุกครั้งเมื่อบางคน () ทำอย่างนั้นในแบบที่หรูหรากว่า โปรดจำไว้ว่าหากคุณใช้งานจาวาสคริปต์เป็นภาษาที่ใช้งานได้คุณไม่ควรใช้สิ่งเหล่านี้ในการควบคุมโครงสร้างของ / ในขณะที่ / เวลา / หยุดพัก นั่นเป็นเหตุผลที่ foreach ค้นหาบางอย่างมีอยู่จริง
Adrian Rodriguez

คำตอบ:


264

ไม่มีวิธีทำเช่นนี้ ดูhttps://github.com/angular/angular.js/issues/263 ขึ้นอยู่กับสิ่งที่คุณทำคุณสามารถใช้บูลีนเพื่อไม่เข้าไปในเนื้อความของวง สิ่งที่ต้องการ:

var keepGoing = true;
angular.forEach([0,1,2], function(count){
  if(keepGoing) {
    if(count == 1){
      keepGoing = false;
    }
  }
});

45
ฉันอยากจะเพิ่ม a !keepGoing && return;ไปไว้ด้านบนสุดของฟังก์ชั่นโดยใช้โค้ดให้น้อยลง
Andrew Joslin

46
นี่ไม่ใช่วิธีปฏิบัติที่ดีที่สุดที่นี่สำหรับการเคลื่อนที่เชิงมุมแต่ละวงไม่เคยหยุดและไม่มีอะไรจะทำลายเชิงมุมได้ เนทีฟสำหรับลูปนั้นเร็วกว่า angular.for ประมาณ 90% ดังนั้นจะเป็นการดีกว่าถ้าใช้ native for loop เมื่อคุณต้องการหยุดการจับคู่เงื่อนไข ขอบคุณ
Nishchit Dhanani

xcatly ที่ฉันติดอยู่ ... และสิ่งนี้ช่วยได้ ... ขอบคุณมาก ... ยังไงก็ตามฉันอยากจะรู้ว่าเหตุผลที่ทำให้วงแต่ละวงแตกไม่ได้ ถ้ามี
Saurabh Tiwari

นี่ไม่ควรเป็นคำตอบที่ได้รับการยอมรับเพราะจะไม่ทำให้ลูป forEach แตก มันเป็นวิธีที่จะไม่ใช้ตรรกะทั้งหมดภายในลูป
Nebulosar

296

การangular.forEachวนซ้ำไม่ตรงกับเงื่อนไข

คำแนะนำส่วนตัวของฉันคือการใช้พื้นเมืองสำหรับangular.forEachห่วงแทน

NATIVE FOR loop เร็วขึ้นประมาณ90% และ loop อื่น ๆ

สำหรับการแบ่งลูปสำหรับผลการทดสอบลูป

ใช้สำหรับวงใน ANGULAR:

var numbers = [0, 1, 2, 3, 4, 5];

for (var i = 0, len = numbers.length; i < len; i++) {
  if (numbers[i] === 1) {
    console.log('Loop is going to break.'); 
    break;
  }
  console.log('Loop will continue.');
}

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ทั้งหมดนี้เสร็จสิ้นการวนซ้ำของลูป แต่จากนั้นมันจะไปยังการทำซ้ำครั้งถัดไป
Ben

1
@ Ben, ขออภัย Ben, มันเป็นความผิดพลาดของฉัน แต่ตอนนี้ฉันอัพเดตคำตอบของฉันหลังจากการค้นคว้ามานาน ฉันหวังว่านี่จะช่วยคุณได้ ขอขอบคุณ
Nishchit Dhanani

1
@LGama: - กรณีของคุณคืออะไร ??
Nishchit Dhanani

3
jsperf.com/angular-foreach-performanceทดสอบบนเบราว์เซอร์ของคุณเองเพื่อตัดสินใจว่าควรเลือกฟังก์ชันใด ฉันได้ทดสอบกับ IE11 แล้วและมันก็เร็วเหมือนในสกรีนช็อตด้วย ทดสอบด้วย Array.some () แต่ช้ากว่า Array.forEach () บน IE11 แต่อาจเร็วกว่านั้น angular.foreach ;-) หรือทดสอบที่นี่jsperf.com/angular-foreach-vs-native (เครดิตทั้งหมดไปที่ผู้เขียนต้นฉบับไม่ใช่ฉัน ;-))
เซบาสเตียน

6
แม้ว่า jsperf คุณจะไม่สามารถพูดว่า "native for for คือเร็วขึ้นประมาณ 90%" ในสถานการณ์ของคุณสิ่งนี้ขึ้นอยู่กับว่าการดำเนินการของฟังก์ชั่นภายในมีค่าใช้จ่ายเท่าใดและสามารถบันทึกการประมวลผลจำนวนเท่าใดโดยออกจากลูป (หยุด) ก่อน
hgoebl

22

กรุณาใช้บางกรณีหรือทุกกรณีของ ForEach

Array.prototype.some:
some is much the same as forEach but it break when the callback returns true

Array.prototype.every:
every is almost identical to some except it's expecting false to break the loop.

ตัวอย่างสำหรับบางคน:

var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];

ary.some(function (value, index, _ary) {
    console.log(index + ": " + value);
    return value === "JavaScript";
});

ตัวอย่างสำหรับทุกคน:

var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];

ary.every(function(value, index, _ary) {
    console.log(index + ": " + value);
    return value.indexOf("Script") > -1;
});

ค้นหาข้อมูลเพิ่มเติมได้ที่
http://www.jsnoob.com/2013/11/26/how-to-break-the-foreach/


no @ AngelS.Moreno ทุกคนชอบใช้ตัวแปรโลคัลแทนวิธีที่ออกแบบมาเป็นพิเศษสำหรับเคสในมือ
Oded Niv

18

ใช้อาเรย์บางวิธี

 var exists = [0,1,2].some(function(count){
      return count == 1
 });

มีอยู่จะกลับมาจริงและคุณสามารถใช้สิ่งนี้เป็นตัวแปรในการทำงานของคุณ

if(exists){
    console.log('this is true!')
}

Array Some Method - Javascript


4
สำหรับผมเหตุผลเดียวที่จะใช้angular.forEach()เป็นที่ฉันได้ให้การสนับสนุน IE8 ซึ่งไม่ได้Array.forEach()... Array.some()หรือ
Bennett McElwee

2
คุณสามารถ polyfill Array.forEach ได้อย่างง่ายดาย ดูด้านล่างของหน้า: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

6

เท่าที่ฉันรู้ Angular ไม่ได้มีฟังก์ชั่นดังกล่าว คุณอาจต้องการใช้find()ฟังก์ชันขีดล่างสำหรับสิ่งนี้ (โดยทั่วไปแล้วจะเป็น forEach ซึ่งแยกออกจากลูปเมื่อฟังก์ชันส่งคืนค่าจริง)

http://underscorejs.org/#find


การทำเช่นนี้อาจช่วยแก้ปัญหาได้ในภายหลัง แต่มันไม่ได้เป็นการทำลายลูป
Elise Chant

หรือมีถิ่นกำเนิดเป็นลูป
shanti

6

หากคุณใช้ jQuery (ไม่ใช่ jqLite) ร่วมกับ AngularJS คุณสามารถวนซ้ำด้วย $ .each - ซึ่งอนุญาตให้ใช้การแยกและดำเนินการต่อโดยยึดตามนิพจน์ค่าบูลีน

JSFiddle:

http://jsfiddle.net/JEcD2/1/

javascript:

var array = ['foo', 'bar', 'yay'];
$.each(array, function(index, element){
    if (element === 'foo') {
        return true; // continue
    }
    console.log(this);
    if (element === 'bar') {
        return false; // break
    }
});

บันทึก:

แม้ว่าการใช้ jQuery นั้นไม่ได้เลวร้ายทั้งMDNและArray.everyฟังก์ชั่นพื้นเมืองได้รับการแนะนำโดย MDN เนื่องจากคุณสามารถอ่านได้ที่ native forEach แต่ละเอกสาร:

"ไม่มีทางหยุดหรือทำลายวน forEach ได้วิธีแก้ปัญหาคือใช้ Array.every หรือ Array.some"

ตัวอย่างต่อไปนี้จัดทำโดย MDN:

Array.some:

function isBigEnough(element, index, array){
    return (element >= 10);
}
var passed = [2, 5, 8, 1, 4].some(isBigEnough);
// passed is false
passed = [12, 5, 8, 1, 4].some(isBigEnough);
// passed is true

Array.every:

function isBigEnough(element, index, array){
    return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
passed = [12, 54, 18, 130, 44].every(isBigEnough);
// passed is true

6

ในทางกลับกันคุณสามารถออกจากforEachลูปและที่ใดก็ได้ยกเว้น

try {
   angular.forEach([1,2,3], function(num) {
      if (num === 2) throw Error();
   });
} catch(e) {
    // anything
}

อย่างไรก็ตามมันจะดีกว่าถ้าคุณใช้ไลบรารี่อื่นหรือใช้ฟังก์ชั่นของคุณเองฟังfindก์ชั่นในกรณีนี้ดังนั้นโค้ดของคุณจึงอยู่ในระดับสูงที่สุด


10
คุณตอบคำถามแล้ว! ฉันหวังว่าไม่มีใครไม่ว่าแม้ว่า :)
เจสันคอคส์

การโยนข้อยกเว้นโดยไม่จำเป็นนั้นไม่ใช่วิธีที่ดีในการจัดการกับสถานการณ์ ค่อนข้างตรวจสอบวิธีการแก้ปัญหาที่มีให้โดย @ dnc253 stackoverflow.com/a/13844508/698127
Aamol


3

ในฐานะที่เป็นคำตอบอื่น ๆ Angular ไม่ได้มีฟังก์ชันนี้ อย่างไรก็ตาม jQuery ทำและถ้าคุณโหลด jQuery รวมถึง Angular คุณสามารถใช้

jQuery.each ( array, function ( index, value) {
    if(condition) return false; // this will cause a break in the iteration
})

ดูhttp://api.jquery.com/jquery.each/


2
สหกรณ์ถามหาวิธีการแก้ปัญหา AngularJS คำตอบที่ถูกต้องคือไม่ :)
แชนนอน Hochkins

3

โดยปกติแล้วจะไม่มีทางแยกลูป "แต่ละ" ในจาวาสคริปต์ สิ่งที่สามารถทำได้คือการใช้วิธี "ลัดวงจร"

    array.forEach(function(item) {
      // if the condition is not met, move on to the next round of iteration.
      if (!condition) return;

      // if the condition is met, do your logic here
      console.log('do stuff.')
    }


2

break เป็นไปไม่ได้ที่จะประสบความสำเร็จในเชิงมุมสำหรับแต่ละเราจำเป็นต้องแก้ไขให้แต่ละคนทำเช่นนั้น

$scope.myuser = [{name: "Ravi"}, {name: "Bhushan"}, {name: "Thakur"}];  
                angular.forEach($scope.myuser, function(name){
                  if(name == "Bhushan") {
                    alert(name);
                    return forEach.break(); 
                    //break() is a function that returns an immutable object,e.g. an empty string
                  }
                });

คำตอบนี้ดูเหมือนจะไม่สมบูรณ์ โปรดระบุว่าbreak()จำเป็นต้องกำหนดหรือว่าเป็นส่วนหนึ่งของเชิงมุมอยู่แล้ว โปรดกำหนดถ้าไม่
ภูมิศาสตร์

2

คุณสามารถใช้สิ่งนี้:

var count = 0;
var arr = [0,1,2];
for(var i in arr){
   if(count == 1) break;
   //console.log(arr[i]);
}

1
var ary = ["JavaScript", "Java", "CoffeeScript", "TypeScript"];
var keepGoing = true;
ary.forEach(function(value, index, _ary) {
    console.log(index)
    keepGoing = true;
    ary.forEach(function(value, index, _ary) {
        if(keepGoing){ 
            if(index==2){
                keepGoing=false;
            }
            else{
                console.log(value)
            }

        }      
    });
});

0
$scope.arr = [0, 1, 2];  
$scope.dict = {}
for ( var i=0; i < $scope.arr.length; i++ ) {
    if ( $scope.arr[i] == 1 ) {
        $scope.exists = 'yes, 1 exists';
        break;
    }
 }
 if ( $scope.exists ) {
     angular.forEach ( $scope.arr, function ( value, index ) {
                      $scope.dict[index] = value;
     });
 }

0

ฉันต้องการทำสิ่งนี้โดยการส่งคืน ใส่ส่วนการวนซ้ำในฟังก์ชั่นส่วนตัวและกลับมาเมื่อคุณต้องการที่จะทำลายวง


0

ฉันรู้ว่านี่เก่า แต่ตัวกรองอาร์เรย์อาจทำสิ่งที่คุณต้องการ:

var arr = [0, 1, 2].filter(function (count) {
    return count < 1;
});

จากนั้นคุณสามารถเรียกใช้arr.forEachและฟังก์ชันอาร์เรย์อื่น ๆ

ฉันรู้ว่าถ้าคุณตั้งใจที่จะลดการดำเนินการวนซ้ำทั้งหมดนี้อาจจะไม่ทำสิ่งที่คุณต้องการ whileสำหรับสิ่งที่คุณใช้งานที่ดีที่สุด


0

ตัวอย่างนี้ใช้ได้ ลองมัน.

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

1
ฉันเดาว่าเขาไม่ต้องการforลูปกรณีการใช้งานของเขาต้องforeachไม่forน่าจะเป็น
Hassen Ch


0
onSelectionChanged(event) {
    let selectdata = event['api']['immutableService']['gridOptionsWrapper']['gridOptions']['rowData'];
    let selected_flag = 0;

    selectdata.forEach(data => {
      if (data.selected == true) {
        selected_flag = 1;
      }
    });

    if (selected_flag == 1) {
      this.showForms = true;
    } else {
      this.showForms = false;
    }
}

-1

ผมจะใช้แทนreturnbreak

angular.forEach([0,1,2], function(count){
  if(count == 1){
    return;
  }
});

ทำงานเหมือนจับใจ


นี่ไม่ใช่ทางออกที่ถูกต้อง look: การทดสอบฟังก์ชั่น () {angular.forEach ([1,2,3,4,5,6,7,8,9]) ฟังก์ชั่น (ค่าดัชนี) {if (value == 2) return; console.log (ค่า);})} เอาต์พุต:> teste (); 1 3 4 5 6 7 8 9
otaviodecampos

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.