Array.forEach ngắn mạch như ngắt cuộc gọi


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

Làm cách nào để sử dụng forEachphương thức mới này trong JavaScript? Tôi đã thử return;, return false;break. breakgặp sự cố và returnkhông làm gì ngoài việc tiếp tục lặp lại.


6
Điều đáng chú ý là trong khi returnthực sự tiếp tục lặp lại, nó sẽ bỏ qua bất kỳ mã nào đi sau nó trong khối. Lấy mã này làm ví dụ : [1,2,3].forEach(function(el) { if(el === 2) { console.log(`Match on 2!`); return; } console.log(el); });. console.log(el);Sẽ bị bỏ qua khi 2 được khớp.
Shane

5
TL; DR: Tôi sẽ tiết kiệm cho bạn rất nhiều thời gian. Gần đây tôi đã sử dụng rất nhiều JS. Câu trả lời (trong số 28 ...) mà bạn có thể đang tìm kiếm là câu trả lời này: stackoverflow.com/a/32101207/1599699
Andrew

Câu trả lời:


2142

Không có khả năng tích hợp để breakvào forEach. Để làm gián đoạn thực thi, bạn sẽ phải ném một ngoại lệ nào đó. ví dụ.

var BreakException = {};

try {
  [1, 2, 3].forEach(function(el) {
    console.log(el);
    if (el === 2) throw BreakException;
  });
} catch (e) {
  if (e !== BreakException) throw e;
}

Các ngoại lệ JavaScript không đẹp lắm. Một forvòng lặp truyền thống có thể phù hợp hơn nếu bạn thực sự cần breakbên trong nó.

Sử dụng Array#some

Thay vào đó, sử dụng Array#some:

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

Điều này hoạt động bởi vì sometrả về truengay khi bất kỳ cuộc gọi lại nào, được thực hiện theo thứ tự mảng, trả về true, làm ngắn mạch việc thực hiện phần còn lại.

some, nghịch đảo của nó every(sẽ dừng trên a return false) và forEachlà tất cả các phương thức ECMAScript Fifth Edition cần được thêm vào các Array.prototypetrình duyệt mà chúng bị thiếu.


111
Điều này không dễ đọc hơn, cũng không hiệu quả hơn là chỉ sử dụng một vòng lặp for thông thường. Câu trả lời phải là "không sử dụng forEach trong trường hợp này" -1
BT

37
Tôi nghĩ rằng "một số" vẫn ổn ở đây, tại sao không sử dụng tối ưu hóa lối ra
sớm-

28
Cảm ơn bạn đã quan tâm someevery, điều này nên được lên TOP trong câu trả lời. Không thể hiểu tại sao mọi người nghĩ rằng nó ít đọc hơn. Thật tuyệt vời!
Karl Adler

9
Việc sử dụng Array#somelà thực sự tốt đẹp. Đầu tiên, nó tương thích với hầu hết các trình duyệt bao gồm eg9 và firefox 1.5 cũng hoạt động rất tốt. Trường hợp sử dụng ví dụ của tôi sẽ là tìm chỉ mục trong một mảng các phạm vi [a, b] trong đó một số nằm giữa một cặp ranh giới dưới và cặp trên, kiểm tra và trả về true khi tìm thấy. for..ofsẽ là giải pháp tốt nhất tiếp theo mặc dù chỉ dành cho các trình duyệt mới hơn.
Sojimaxi

96
Xử lý ngoại lệ KHÔNG BAO GIỜ được sử dụng như luồng điều khiển. GIAI ĐOẠN = STAGE.
thẳng thắn

479

Bây giờ có một cách thậm chí tốt hơn để làm điều này trong ECMAScript2015 (còn gọi là ES6) bằng cách sử dụng vòng lặp for mới . Ví dụ, mã này không in các phần tử mảng sau số 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;
  }
}

Từ các tài liệu:

Cả cho ... trongcho ... các tuyên bố lặp đi lặp lại trên một cái gì đó. Sự khác biệt chính giữa chúng là ở những gì chúng lặp đi lặp lại. Câu lệnh for ... lặp đi lặp lại trên các thuộc tính có thể đếm được của một đối tượng, theo thứ tự chèn ban đầu. Dấu ... của câu lệnh lặp trên dữ liệu mà đối tượng lặp có thể định nghĩa được lặp lại.

Cần chỉ số trong vòng lặp? Bạn có thể sử dụng Array.entries():

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

4
@superhero Bạn có thể lấy chỉ mục của phần tử trong một ... vòng lặp, bạn chỉ cần sử dụng entries. for (const [index, phần tử] của someArray.entries ()) {// ...}
bôi đen

không nên sử dụng cho ... trong với mảng?
schehata

4
@emostafa Bạn là chính xác về cho trong vòng không được khuyến khích cho các mảng, nhưng đây là cách tiếp cận thực sự sử dụng một cho các vòng lặp.
canac

Đây là "cho" và đây là một giải pháp thực sự sạch sẽ ... nhưng đây cũng là một tính năng ES6, vì vậy hãy lưu ý rằng điều này sẽ chỉ hoạt động nếu môi trường của bạn được thiết lập cho ES6.
Chad

Tôi thấy mình sử dụng giải pháp này rất nhiều và tôi cũng sử dụng nó cho các đối tượng. Với các đối tượng, bạn có thể làm Object.entries(myObject)và sau đó sử dụng nó chính xác như bạn sử dụng for..incho mảng. Lưu ý rằng các mảng JS về cơ bản là các đối tượng dưới mui xe: blog.niftysnippets.org/2011/01/myth-of-arrays.html
Andrew

204

Bạn có thể sử dụng mọi phương pháp:

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

ES6

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

để sử dụng hỗ trợ trình duyệt cũ:

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

biết thêm chi tiết tại đây .


10
Đẹp và sạch sẽ trong ES6 bây giờ -[1,2,3].every( el => el !== 1 )
metame

1
@Valdemar, nhưng có every đảm bảo rằng các cuộc gọi được thực hiện theo trình tự không?
Pacerier

4
@Pacerier, bạn có thể thấy thuật toán trong đặc tả ES6 rằng chỉ số kbắt đầu từ 0 và được tăng thêm 1: http
XP1

@ XP1, Có phải tất cả những người triển khai đều phải làm theo cách đó không?
Pacerier

1
@Pacerier, vâng, hầu hết các triển khai phổ biến đều hoạt động đúng. Nếu bạn lo ngại về việc triển khai nhúng, thường là Opera hoặc webkit. Phương thức mỗi cuộc gọi callbackfn một lần cho mỗi phần tử có trong mảng, theo thứ tự tăng dần , cho đến khi nó tìm thấy một trong đó callbackfn trả về false. Cũng xem bước 7. Đặt k là 0. và 8.e Tăng k thêm 1.
Valdemar_Rudolfovich

78

Trích dẫn từ tài liệu MDN củaArray.prototype.forEach() :

Không có cách nào để ngăn chặn hoặc phá vỡ một forEach()vòng lặp ngoài việc ném một ngoại lệ. Nếu bạn cần hành vi như vậy, .forEach()phương pháp là công cụ sai , thay vào đó hãy sử dụng một vòng lặp đơn giản. Nếu bạn đang kiểm tra các phần tử mảng cho một vị từ và cần một giá trị trả về boolean, bạn có thể sử dụng every()hoặc some()thay vào đó.

Đối với mã của bạn (trong câu hỏi), như được đề xuất bởi @bobince, hãy sử dụng Array.prototype.some()thay thế. Nó rất phù hợp với usecase của bạn.

Array.prototype.some()thực thi hàm gọi lại một lần cho mỗi phần tử có trong mảng cho đến khi nó tìm thấy một trong đó gọi lại trả về một giá trị trung thực (một giá trị trở thành đúng khi được chuyển đổi thành a Boolean). Nếu một yếu tố như vậy được tìm thấy, some()ngay lập tức trả về đúng. Nếu không, some()trả về false. gọi lại chỉ được gọi cho các chỉ mục của mảng đã gán giá trị; nó không được gọi cho các chỉ mục đã bị xóa hoặc chưa bao giờ được gán giá trị.


1
Đây là câu trả lời chính xác. 'một số' thực hiện chính xác những gì một foreach / break sẽ làm. Nó lặp cho đến khi lặp n = true.
Gian hàng Antony

74

Thật không may trong trường hợp này sẽ tốt hơn nhiều nếu bạn không sử dụng forEach. Thay vào đó sử dụng một forvòng lặp thông thường và bây giờ nó sẽ hoạt động chính xác như bạn mong đợi.

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

27
Tôi choáng váng rằng phiếu bầu cao nhất là sự thực thi tồi tệ nhất có thể, so với hiệu suất cao hơn, ít mã hơn và khả năng đọc tốt hơn của câu trả lời đúng này. Ném ngoại lệ ... thật sao? Là vòng lặp truyền thống chỉ là không đủ kewl?
gdbj

2
@gdbj Tôi đồng ý với tuyên bố của bạn và đã sử dụng phương pháp này, nhưng điều thực sự gây sốc cho tôi là không có cách nào thoát khỏi forEach mà không có các bản hack này, bây giờ đó là thiết kế tồi.
ScottN

28

Cân nhắc sử dụng jquerycủa eachphương pháp, vì nó cho phép trở về chức năng bên trong gọi lại sai:

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

Thư viện Lodash cũng cung cấp takeWhilephương thức có thể được kết nối với map / less / Fold, v.v.

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

1
Lý do tốt để sử dụng jQuery. forEach trong javascript gốc vẫn còn thiếu.
Alex Grande

3
@AlexGrande forEach của jQuery và forEach của JavaScript không tương thích.
Bjorn

10
JavaScript được sử dụng ở nhiều nơi mà jQuery không phải là một tùy chọn.
JBRWilkinson


18

Nếu bạn muốn sử dụng đề xuất của Dean Edward và ném lỗi StopIteration để thoát khỏi vòng lặp mà không phải bắt lỗi, bạn có thể sử dụng hàm sau ( ban đầu từ đây ):

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

Đoạn mã trên sẽ cung cấp cho bạn khả năng chạy mã như sau mà không cần phải thực hiện các mệnh đề thử của riêng bạn:

// Show the contents until you get to "2".
[0,1,2,3,4].forEach(function(val) {
  if(val == 2)
    throw StopIteration;
  alert(val);
});

Một điều quan trọng cần nhớ là điều này sẽ chỉ cập nhật hàm Array.prototype.forEach nếu nó đã tồn tại. Nếu nó chưa tồn tại, nó sẽ không sửa đổi nó.


11

Câu trả lời ngắn: sử dụng for...breakcho việc này hoặc thay đổi mã của bạn để tránh phá vỡ forEach. Không sử dụng .some()hoặc .every()thi đua for...break. Viết lại mã của bạn để tránh for...breakvòng lặp, hoặc sử dụng for...break. Mỗi khi bạn sử dụng các phương pháp này như for...breakChúa thay thế giết chết mèo con.

Câu trả lời dài:

.some().every()cả hai booleangiá trị .some()trả về , trả về truenếu có bất kỳ phần tử nào mà hàm đã qua trả về true, mỗi trả về falsenếu có bất kỳ phần tử nào mà hàm được truyền trả về false. Đây là những gì chức năng có nghĩa. Sử dụng các hàm cho những gì chúng không có nghĩa là tồi tệ hơn nhiều sau đó sử dụng các bảng để bố trí thay vì CSS, vì nó làm nản lòng tất cả những ai đọc mã của bạn.

Ngoài ra, cách duy nhất có thể để sử dụng các phương pháp này for...breakthay thế là tạo hiệu ứng phụ (thay đổi một số vars bên ngoài .some()chức năng gọi lại) và điều này không khác nhiều for...break.

Vì vậy, sử dụng .some()hoặc .every()như for...breakvòng lặp thay thế là không được tự do tác dụng phụ, đây không phải là nhiều bụi sau đó for...break, đây là bực bội, vì vậy đây không phải là tốt hơn.

Bạn luôn có thể viết lại mã của mình để không có nhu cầu for...break. Bạn có thể lọc mảng bằng cách sử dụng .filter(), bạn có thể phân chia mảng bằng cách sử dụng .slice(), v.v., sau đó sử dụng .forEach()hoặc .map()cho phần đó của mảng.


sử dụng .filter thực sự là giải pháp thích hợp cho rất nhiều trường hợp sử dụng để phá vỡ.
TKoL

Hiệu suất thì sao? Bộ lọc không ảnh hưởng đến hiệu suất nếu được sử dụng thường xuyên?
tfrascaroli

Có, nguyên mẫu mảng bộ lọc có thể trở nên nặng nề. Tôi thích nó, nhưng nó có thể ảnh hưởng đến hiệu suất nếu nó được sử dụng quá mức.
Chad

@tfrascaroli sử dụng for...breakvòng lặp nếu bạn cần hiệu suất. forvòng lặp là công cụ nhất performant lặp hơn .forEach(), .any(), .map(), .filter(), vv
Max

6

Đây chỉ là thứ tôi nghĩ ra để giải quyết vấn đề ... Tôi khá chắc chắn rằng nó đã khắc phục vấn đề mà người hỏi ban đầu gặp phải:

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

Và sau đó bạn sẽ gọi nó bằng cách sử dụng:

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

Trả về false bên trong chức năng gọi lại sẽ gây ra sự cố. Hãy cho tôi biết nếu điều đó không thực sự làm việc.


1
=== falsecó thể tốt hơn == falsevì vậy bạn không cần phải trả lại đúng (hoặc giá trị trung thực) để tiếp tục vòng lặp, vì sợ rằng một số đường dẫn điều khiển không trả về giá trị và vòng lặp bị phá vỡ bất ngờ.
Jake

6

Một khái niệm khác tôi đã đưa ra:

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


Cú pháp tương tự như [NSArray enum CảObjectsUsingBlock], Cảm ơn!
Chrstph SLN

@Drenai chữ ký tương tự như bản địa Array.prototype.forEach(). forbreaktồn tại rất lâu trước khi câu hỏi này được hỏi; OP đã tìm kiếm hành vi đó bằng cách sử dụng, càng nhiều chức năng , forEach.
c24w

@Drenai hiện đã xóa bình luận của họ (nhưng để lại downvote) trong đó đề cập rằng chữ ký của giải pháp này rất khó nhớ và không cần thiết khi bạn có thể giải quyết vấn đề với for...inbreak.
c24w

6
var array = [1,2,3,4];

for(var item of array){
    console.log(item);
    if(item == 2){
       break;
    }
}

5

Tìm thấy giải pháp này trên một trang web khác. Bạn có thể gói forEach trong một kịch bản thử / bắt.

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

Thêm chi tiết tại đây: http://dean.edwards.name/weblog/2006/07/enum/


2
Đừng sử dụng ngoại lệ như một câu lệnh điều khiển. Sử dụng nó để xử lý kết quả bất ngờ.
Tối đa

4

Nếu bạn không cần truy cập vào mảng của mình sau khi lặp, bạn có thể bảo lãnh bằng cách đặt độ dài của mảng thành 0. Nếu bạn vẫn cần nó sau khi lặp, bạn có thể sao chép nó bằng lát ..

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

Hoặc với một bản sao:

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

Đó là một giải pháp tốt hơn nhiều sau đó ném các lỗi ngẫu nhiên trong mã của bạn.


được thực hiện tốt :) nhưng nếu có một số hành động sau khi gán array.lengthcho 0chúng sẽ được áp dụng trong lần lặp hiện tại, vì vậy có lẽ đôi khi sử dụng tốt hơn returnsau khi gán như vậy
zhibirc

4

Đây là một vòng lặp for, nhưng duy trì tham chiếu đối tượng trong vòng lặp giống như forEach () nhưng bạn có thể thoát ra.

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

4

Như đã đề cập trước đó, bạn không thể phá vỡ .forEach().

Đây là một cách hiện đại hơn một chút để thực hiện một cuộc thảo luận với ES6 Iterators. Cho phép bạn truy cập trực tiếp vào index/ valuekhi lặp.

const array = ['one', 'two', 'three'];

for (const [index, val] of array.entries()) {
  console.log('item:', { index, val });
  if (index === 1) {
    console.log('break!');
    break;
  }
}

Đầu ra:

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

Liên kết


3

Một cách tiếp cận khác

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

2

Tôi sử dụng nullhack cho mục đích đó, nó cố gắng truy cập thuộc tính của null, đó là một lỗi:

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
Tại sao không chỉ throw BREAK?
Bergi

1

Nếu bạn muốn giữ forEachcú pháp của mình , đây là một cách để giữ cho nó hiệu quả (mặc dù không tốt như vòng lặp thông thường). Kiểm tra ngay một biến để biết nếu bạn muốn thoát ra khỏi vòng lặp.

Ví dụ này sử dụng hàm ẩn danh để tạo phạm vi hàm xung quanh forEachmà bạn cần lưu trữ thông tin đã thực hiện .

(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>

Theo quan điểm của tôi.


1

Tôi biết nó không đúng cách. Nó không phá vỡ vòng lặp. Nó là một con Jugad

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



0

Đồng ý với @bobince, được nâng cấp.

Ngoài ra, FYI:

Prototype.js có một cái gì đó cho mục đích này:

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

$break sẽ được Prototype.js bắt và xử lý bên trong, phá vỡ chu trình "mỗi" nhưng không tạo ra các lỗi bên ngoài.

Xem API Prototype.JS để biết chi tiết.

jQuery cũng có một cách, chỉ cần trả về false trong trình xử lý để phá vỡ vòng lặp sớm:

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

  });
</script>

Xem API jQuery để biết chi tiết.


0

Đây không phải là hiệu quả nhất, vì bạn vẫn xoay vòng tất cả các yếu tố, nhưng tôi nghĩ rằng nó có thể đáng để xem xét rất đơn giản:

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

continuelà một từ khóa, mã của bạn là một lỗi cú pháp.
Bergi

3
Vì dù sao bạn cũng đang sử dụng ES6, bạn chỉ nên chuyển sang một for ofvòng lặp và break;từ đó như bình thường.
Bergi

đã sửa và đúng - nhưng chủ yếu là sử dụng es6 cho ngắn gọn
martyman

0

bạn có thể làm theo đoạn mã dưới đây phù hợp với tôi:

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

Tại sao là -1? Nó không xấu hơn bắt một ngoại lệ, đó là một vụ hack lớn hơn IMHO.
Byron Whitlock

0

Tôi thích sử dụng 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 inhoạt động giống như forEach, và bạn có thể thêm hàm return để thoát bên trong. Hiệu suất tốt hơn quá.


0

Nếu bạn cần ngắt dựa trên giá trị của các phần tử đã có trong mảng như trong trường hợp của bạn (nghĩa là nếu điều kiện ngắt không phụ thuộc vào biến thời gian chạy có thể thay đổi sau khi mảng được gán giá trị phần tử của nó), bạn cũng có thể sử dụng kết hợp của lát ()indexOf () như sau.

Nếu bạn cần ngắt khi forEach đạt đến 'Apple', bạn có thể sử dụng

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

Như đã nêu trong W3Schools.com , phương thức lát () trả về các phần tử được chọn trong một mảng, dưới dạng một đối tượng mảng mới. Mảng ban đầu sẽ không được thay đổi.

Xem nó trong JSFiddle

Hy vọng nó sẽ giúp được ai đó.


0

Bạn có thể tạo một biến thể của forEachcho phép break, continue, return, và thậm chí async/ await: (ví dụ viết bằng nguyên cảo)

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

Sử dụng:

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

-1

thử với "tìm":

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

-1

Có, có thể tiếp tục và thoát khỏi vòng lặp forEach.

Để tiếp tục, bạn có thể sử dụng return, vòng lặp sẽ tiếp tục nhưng chức năng hiện tại sẽ kết thúc.

Để thoát khỏi vòng lặp, bạn có thể đặt tham số thứ ba thành 0 độ dài, đặt thành mảng trống. Vòng lặp sẽ không tiếp tục, hàm hiện tại làm, vì vậy bạn có thể sử dụng "return" để kết thúc, như thoát trong vòng lặp bình thường ...

Điều này:

[1,2,3,4,5,6,7,8,9,10].forEach((a,b,c) => {
    console.log(a);
    if(b == 2){return;}
    if(b == 4){c.length = 0;return;}
    console.log("next...",b);
});

sẽ in cái này:

1
next... 0
2
next... 1
3
4
next... 3
5

-2

Trước đây, mã của tôi ở dưới

 this.state.itemsDataSource.forEach((item: any) => {
                if (!item.isByPass && (item.invoiceDate == null || item.invoiceNumber == 0)) {

                    return false;
                }
            });

Tôi đã thay đổi để dưới đây, nó đã được sửa chữa.

 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)) {

                    return false;
                }
            }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.