Pertanyaan Bagaimana cara melakukan hubungan singkat Array.forEach seperti call break?


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

Bagaimana saya bisa melakukan ini menggunakan yang baru forEach metode di JavaScript? Saya sudah mencoba "kembali", "kembali palsu" dan "istirahat". Memecahkan crash dan kembali tidak melakukan apa-apa kecuali melanjutkan iterasi.


1008
2018-04-14 21:57


asal


Jawaban:


Tidak ada kemampuan built-in untuk break di forEach. Untuk menginterupsi eksekusi, Anda harus membuat pengecualian. misalnya.

var BreakException = {};

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

Pengecualian JavaScript tidak terlalu bagus. Tradisional for lingkaran mungkin lebih tepat jika Anda benar-benar perlu break Didalam itu.

Menggunakan Array#some

Sebaliknya, gunakan Array#some:

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

Ini berfungsi karena some kembali true segera setelah salah satu callback, dieksekusi dalam urutan susunan, kembali true, hubung singkat eksekusi sisanya.

some, kebalikannya every (yang akan berhenti pada return false), dan forEach semua metode ECMAScript Edisi Kelima yang perlu ditambahkan ke Array.prototype di browser di mana mereka hilang.


1404
2018-04-14 22:02



Sekarang ada cara yang lebih baik untuk melakukannya di ECMAScript2015 (alias ES6) menggunakan yang baru untuk loop. Misalnya, kode ini tidak mencetak elemen larik setelah nomor 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;
  }
}

Dari dokumen:

Kedua untuk ... masuk dan untuk ... dari pernyataan mengulangi sesuatu. Perbedaan utama di antara mereka adalah apa yang mereka ulangi. Itu untuk ... masuk pernyataan iterasi atas sifat enumerable dari suatu objek, dalam urutan penyisipan asli. Itu untuk ... dari pernyataan iterates atas data yang menyatakan objek iterable untuk iterasi berakhir.

Perlu indeks dalam iterasi? Kamu dapat memakai Array.entries():

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

165
2017-08-19 16:43



Kamu dapat memakai setiap metode:

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

untuk penggunaan dukungan browser lama:

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

keterangan lebih lanjut sini.


154
2017-07-19 09:18



Mengutip dari Dokumentasi MDN tentang Array.prototype.forEach():

Ada tidak ada cara untuk berhenti atau istirahat Sebuah forEach() loop selain   dengan melempar pengecualian. Jika Anda membutuhkan perilaku seperti itu, itu .forEach() metode adalah alat yang salah, gunakan loop polos sebagai gantinya. Jika Anda menguji elemen larik untuk predikat dan memerlukan nilai pengembalian boolean, Anda dapat menggunakan every() atau some() sebagai gantinya.

Untuk kode Anda (dalam pertanyaan), seperti yang disarankan oleh @bobince, gunakan Array.prototype.some() sebagai gantinya. Ini sangat sesuai dengan usecase Anda.

Array.prototype.some() menjalankan fungsi panggilan balik satu kali untuk setiap elemen yang ada dalam larik sampai ia menemukan di mana callback mengembalikan nilai yang benar (nilai yang menjadi true ketika dikonversi ke Boolean). Jika elemen seperti itu ditemukan, some() segera mengembalikan nilai true. Jika tidak, some() mengembalikan salah. callback dipanggil hanya untuk indeks array yang telah menetapkan nilai; ia tidak dipanggil untuk indeks yang telah dihapus atau yang tidak pernah diberi nilai.


45
2018-01-06 21:16



Sayangnya dalam hal ini akan jauh lebih baik jika Anda tidak menggunakannya forEach. Sebaliknya gunakan yang biasa for loop dan sekarang akan berfungsi seperti yang Anda harapkan.

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

38
2017-08-25 20:03



Pertimbangkan untuk digunakan jquery's each metode, karena memungkinkan untuk mengembalikan fungsi callback palsu di dalam:

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

Lodash libraries juga menyediakan takeWhile metode yang dapat dirantai dengan peta / mengurangi / melipat dll:

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

24
2018-04-14 22:06



Jika Anda ingin menggunakannya Saran Dean Edward dan membuang kesalahan StopIteration untuk keluar dari loop tanpa harus menangkap kesalahan, Anda dapat menggunakan fungsi berikut ini (berasal dari sini):

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

Kode di atas akan memberi Anda kemampuan untuk menjalankan kode seperti berikut tanpa harus mencoba klausa coba-sendiri:

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

Satu hal penting untuk diingat adalah ini hanya akan memperbarui fungsi Array.prototype.forEach jika sudah ada. Jika belum ada, itu tidak akan mengubahnya.


14
2017-07-05 19:32



Dari contoh kode Anda, sepertinya Array.prototype.find adalah apa yang Anda cari: Array.prototype.find () dan Array.prototype.findIndex () 

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

13
2018-01-15 20:20