Apa cara tercepat untuk mengulang melalui array di JavaScript?

248

Saya belajar dari buku bahwa Anda harus menulis untuk loop seperti ini :

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

jadi arr.lengthtidak akan dihitung setiap waktu.

Yang lain mengatakan bahwa kompiler akan melakukan beberapa optimasi untuk ini, jadi Anda bisa menulis:

for(var i=0; i < arr.length; i++){
    // blah blah
}

Saya hanya ingin tahu yang mana cara terbaik dalam latihan?

wong2
sumber
1
juga patut dilihat ketika berhadapan dengan array looping: jsperf.com/array-loop-var-caching
cloakedninjas
@ wong2 Tolok ukur ini dari Browserdiet memiliki koleksi alternatif yang lebih lengkap.
Domi
1
jsben.ch/#/y3SpC
EscapeNetscape
Ditingkatkan pada jsben sebelumnya: jsben.ch/#/R6LbS
Corbfon
Bisakah kita memperkenalkan for ... ofperulangan ke kompetisi ini? Sintaks tampaknya lebih mudah daripada loop untuk tanpa caching, dan saya ingin tahu apakah saya harus beralih menggunakan untuk loop.
programmerRaj

Jawaban:

339

Setelah melakukan tes ini dengan sebagian besar browser modern ...

http://jsben.ch/dyM52

Saat ini , bentuk loop tercepat (dan menurut saya yang paling jelas secara sintaksis).

standar untuk loop dengan caching panjang

for (var i = 0, len = myArray.length; i < len; i++) {

}

Saya akan mengatakan ini jelas merupakan kasus di mana saya memuji pengembang mesin JavaScript. Waktu berjalan harus dioptimalkan untuk kejelasan , bukan kepintaran .

jondavidjohn
sumber
6
Menariknya, di IE9 ini lebih cepat: untuk (var i = 0, len = myArray.length; i <len; ++ i) {} // awalan incr, bukan postfix
Christopher Bennage
4
Lihat Memilih operator awalan dari pada postfix untuk alasan lain penggunaan ++i.
Bennett McElwee
4
Saya diuji menggunakan operator awalan seperti yang disarankan @BennettMcElwee dan berjalan sedikit lebih cepat: for(var i=0, len=myArray.length; i<len; ++i) Periksa jsperf.com/caching-array-length/84
victmo
21
Anda harus berhati-hati menggunakan loop ini. Saya mulai menggunakannya dan mengalami kesulitan melacak bug karena satu kesalahan yang saya buat. Jika Anda membuat dua loop seperti ini: jsfiddle.net/KQwmL/1 . Anda harus berhati-hati memberi nama var len secara berbeda di kedua loop, jika tidak loop kedua akan menimpa len pertama.
Rui Marques
6
@ WillshawMedia Anda dapat mendeklarasikan banyak variabel dengan satu varpernyataan. Bagaimana itu ditulis, lensebenarnya dicakup seperti yang Anda sarankan.
jondavidjohn
90

Cara tercepat mutlak untuk mengulang melalui javascript array adalah:

var len = arr.length;
while (len--) {
    // blah blah
}

Lihat http://blogs.oracle.com/greimer/entry/best_way_to_code_a untuk perbandingan lengkap

gnur
sumber
1
Jangan lupa untuk menggunakan var(yang lain lenmenjadi variabel global). Juga, lihat jsperf.com/loops untuk lebih banyak benchmark loop.
Mathias Bynens
22
Posting blog berdasarkan jawaban ini sekarang hampir 4 tahun, dan banyak yang telah berubah di mesin js pada waktu itu, lihat jawaban saya di bawah ini untuk perbandingan yang diperbarui.
jondavidjohn
1
Saya setuju dengan @jondavidjohn. Saya menguji kode ini dan ternyata menjadi kurang efisien ... Periksa jsperf.com/caching-array-length/84
victmo
Jawaban di atas hampir secara universal (lintas browser) jauh lebih lambat daripada for-loop. Lihat tautan JSPerf dalam jawaban yang diterima. Ini sangat memalukan, karena itu IMO sangat mudah dibaca.
Letharion
3
Saya kira @jondavidjohn bahwa yang Anda maksud dengan 'jawaban saya di bawah' adalah 'jawaban saya di atas' lol.
Shanimal
40

Pada Juni 2016 , melakukan beberapa tes di Chrome terbaru (71% dari pasar browser pada Mei 2016, dan meningkat):

  • Loop tercepat adalah for loop , baik dengan dan tanpa panjang caching memberikan kinerja yang sangat mirip. (The for loop dengan panjang cache kadang-kadang memberikan hasil yang lebih baik daripada yang tanpa caching, tetapi perbedaannya hampir diabaikan, yang berarti mesin mungkin sudah dioptimalkan untuk mendukung standar dan mungkin paling mudah untuk loop tanpa caching).
  • Loop sementara dengan penurunan kira-kira 1,5 kali lebih lambat dari loop for.
  • Sebuah loop menggunakan fungsi callback (seperti forEach standar), kira-kira 10 kali lebih lambat daripada for loop.

Saya percaya utas ini terlalu lama dan itu adalah programer menyesatkan untuk berpikir mereka perlu panjang cache, atau menggunakan reverse traversing sementara dengan pengurangan untuk mencapai kinerja yang lebih baik, menulis kode yang kurang terbaca dan lebih rentan terhadap kesalahan daripada mudah untuk loop sederhana. Karena itu, saya merekomendasikan:

  • Jika aplikasi Anda berulang pada banyak item atau kode loop Anda ada di dalam fungsi yang sering digunakan, jawaban langsung untuk loop adalah jawabannya:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • Jika aplikasi Anda tidak benar-benar beralih melalui banyak item atau Anda hanya perlu melakukan iterasi kecil di sana-sini, menggunakan standar untuk setiap panggilan balik atau fungsi serupa dari perpustakaan JS pilihan Anda mungkin lebih mudah dimengerti dan lebih rentan terhadap kesalahan, karena lingkup variabel indeks ditutup dan Anda tidak perlu menggunakan tanda kurung, mengakses nilai array secara langsung:

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
  • Jika Anda benar-benar perlu menggaruk beberapa milidetik saat iterasi lebih dari miliaran baris dan panjang array Anda tidak berubah melalui proses, Anda mungkin mempertimbangkan untuk caching panjang dalam for loop Anda. Meskipun saya pikir ini benar-benar tidak perlu saat ini:

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }
CGodo
sumber
Nggak. jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 menunjukkan bahwa yang tercepat adalah "Loop terbalik, perbandingan implisit, kode berurutan" (105,221 ops / detik) sementara "Loop, nilai cache, kode inlined" hanya mencetak 76.635 ops / detik (Chrome 38.0.212.111 )
Fr0sT
@ Fr0sT Patokan Anda adalah skenario yang berbeda, melintasi array dari indeks 1 ke <= panjang. Tentu saja ini akan mengarah pada hasil yang berbeda. Jika Anda mencoba melintasi array berbasis nol dengan <panjang - yang menurut saya ini adalah skenario biasa - Anda akan menemukan bahwa hasilnya lebih baik dioptimalkan dengan loop "for" yang normal (dengan panjang cache sedikit lebih cepat).
CGodo
Kyopaxa mengubah tolok ukur menjadi (0 <= i <panjang), hasilnya sama. "Reverse loop, perbandingan implisit, panggilan fungsi" mencetak 365 kops / dtk, sementara "Loop, nilai cache, kode sebaris" mencetak 350 kops / dtk (FF 51)
Fr0sT
@ Fr0sT jika Anda mengubah cache untuk-loop berbasis nol tanpa perbandingan yang sama, seperti for(let i=0, j=array.length; i < j; i++), maju untuk loop mempercepat jauh. Pada beberapa tes saya menjalankannya menang, pada sebagian besar itu berada dalam margin of error atau loop terbalik.
Isaac B
1
@ IsaacB dan semua, maaf saya tidak melihat bahwa bangku cukup salah - semua loop langsung iterate 1..length sementara reverse loop iterate length..0 (arr [length] item tidak valid). Saya memperbaiki tes dan sekarang mereka menunjukkan hasil sebagai berikut: "Loop, kode sebaris" 360,616 ops / detik ± 0,27%, "Loop, nilai cache, kode sebaris" 345.786 ops / detik ± 2,18% (Sic!) "Loop terbalik, perbandingan implisit, kode sebaris "322.640 ops / dt ± 2.90% (!!!). Tes dieksekusi oleh FF51. Bangku baru ada di sini jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 . Jadi sepertinya tidak masuk akal untuk membatalkan loop.
Fr0sT
31

Jika urutannya tidak penting, saya lebih suka gaya ini:

for(var i = array.length; i--; )

Tembolok itu panjangnya dan jauh lebih pendek untuk menulis. Tapi itu akan beralih ke array dalam urutan terbalik.

Felix Kling
sumber
6
Anda baru saja membunuhnya.
Vignesh Raja
tidakkah kamu membutuhkan i> = 0 ;?
MarwaAhmad
3
@MarwaAhmad: Tidak. i--Mengembalikan nomor dan sekali nomor 0kondisi adalah falsekarena Boolean(0) === false.
Felix Kling
30

Ini hanya 2018 sehingga pembaruan bisa menyenangkan ...

Dan saya benar-benar harus tidak setuju dengan jawaban yang diterima . Ini berlaku pada browser yang berbeda. beberapa melakukan forEachlebih cepat, beberapa for-loop, dan beberapa di while sini adalah patokan pada semua metode http://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

dan karena Anda dapat melihat banyak for-loop seperti for(a = 0; ... )layak untuk disebutkan bahwa tanpa variabel 'var' akan didefinisikan secara global dan ini dapat secara dramatis mempengaruhi kecepatan sehingga akan menjadi lambat.

Perangkat Duff berjalan lebih cepat di opera tetapi tidak di firefox

var arr = arr = new Array(11111111).fill(255);
var benches =     
[ [ "empty", () => {
  for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
  for(var a = 0, l = arr.length; a < l; ++a)
    var b = arr[a] + 1;
}]
, ["for-loop++", () => {
  for(var a = 0, l = arr.length; a < l; a++)
    var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
  for(var a = 0; a < arr.length; ++a )
    var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
  for(var a = arr.length - 1; a >= 0; --a )
    var b = arr[a] + 1;
}]
,["while-loop", () => {
  var a = 0, l = arr.length;
  while( a < l ) {
    var b = arr[a] + 1;
    ++a;
  }
}]
, ["reverse-do-while-loop", () => {
  var a = arr.length - 1; // CAREFUL
  do {
    var b = arr[a] + 1;
  } while(a--);   
}]
, ["forEach", () => {
  arr.forEach( a => {
    var b = a + 1;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
  // Here if you forget to put 'var' so variables'll be global
  for(a = 0, l = arr.length; a < l; ++a)
     var b = arr[a] + 1;
});
var times = benches.map( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [a[0], bench(...a)]
                     }).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div {  clear:both   }
body > div > div > span {
  float:left;
  width:43%;
  margin:3px 0;
  text-align:right;
}
body > div > div > span:nth-child(2) {
  text-align:left;
  background:darkorange;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>

nullqube
sumber
3
@ Maykonn Anda mungkin ingin mengatakan "dan berfungsi di mana-mana selain Opera Mini"
dube
3
@ Maykonn Yang tidak tercantum dalam tampilan default karena 0,18% dari semua pengguna memiliki IE8 dan Anda tidak perlu membuang waktu untuk mencoba mendukungnya; pada tahun 2018 itu adalah kuda mati.
dube
1
Memang benar jika Anda mempertimbangkan semua pengguna di seluruh dunia. Tapi, sayangnya, di bagian dunia tertentu IE8 masih relevan.
Maykonn
1
Jika saya boleh, tidak hanya browser yang berbeda akan memiliki hasil yang berbeda dengan metode yang berbeda, tetapi browser yang sama akan memiliki hasil yang berbeda dengan input yang berbeda pula. Sejumlah besar Array saja akan sangat dioptimalkan, sedangkan yang campuran kecil tidak.
Kaiido
1
@Tahlil Terima kasih.
nullqube
19

2014 Whilekembali

Berpikir logis saja.

Lihat ini

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. Harus membuat setidaknya 2 variabel (indeks, panjang)
  2. Perlu memeriksa apakah indeks lebih kecil dari panjangnya
  3. Perlu meningkatkan indeks
  4. yang forloop 3 parameter

Sekarang katakan padaku mengapa ini harus lebih cepat daripada:

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. Satu variabel
  2. Tanpa cek
  3. indeks berkurang (Mesin lebih suka itu)
  4. while hanya memiliki satu parameter

Saya benar-benar bingung ketika Chrome 28 menunjukkan bahwa for loop lebih cepat daripada sementara. Ini pasti punya semacam

"Eh, semua orang menggunakan for loop, mari kita fokus pada itu ketika mengembangkan untuk chrome."

Tapi sekarang, pada 2014 loop sementara kembali pada chrome. ini 2 kali lebih cepat, di browser lain / yang lebih lama selalu lebih cepat.

Akhir-akhir ini saya membuat beberapa tes baru. Sekarang di dunia nyata, kode-kode pendek itu tidak bernilai apa-apa dan jsperf tidak dapat benar-benar mengeksekusi loop sementara, karena perlu membuat ulang array. Panjang yang juga membutuhkan waktu.

Anda TIDAK BISA mendapatkan kecepatan aktual loop sementara di jsperf.

Anda perlu membuat fungsi kustom Anda sendiri dan memeriksanya window.performance.now()

Dan ya ... tidak mungkin loop sementara hanya lebih cepat.

Masalah sebenarnya adalah manipulasi dom / rendering waktu / waktu menggambar atau bagaimana pun Anda ingin menyebutnya.

Misalnya saya punya adegan kanvas di mana saya perlu menghitung koordinat dan tabrakan ... ini dilakukan antara 10-200 MicroSeconds (bukan milidetik). sebenarnya dibutuhkan berbagai milidetik untuk membuat semuanya. Sama seperti di DOM.

TAPI

Ada cara super performan lain menggunakan untuk loopdalam beberapa kasus ... misalnya untuk menyalin / mengkloning array

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

Perhatikan pengaturan parameter:

  1. Sama seperti pada while loop saya hanya menggunakan satu variabel
  2. Perlu memeriksa apakah indeks lebih besar dari 0;
  3. Seperti yang Anda lihat pendekatan ini berbeda vs normal untuk semua orang menggunakan loop, karena saya melakukan hal-hal di dalam parameter ke-3 dan saya juga mengurangi langsung di dalam array.

Mengatakan itu, ini menegaskan bahwa mesin seperti -

menulis bahwa saya berpikir untuk membuatnya sedikit lebih pendek dan menghapus beberapa barang yang tidak berguna dan menulis yang ini menggunakan gaya yang sama:

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

Bahkan jika lebih pendek sepertinya menggunakan isekali lagi memperlambat segalanya. Ini 1/5 lebih lambat dari forloop sebelumnya dan whilesatu.

Catatan: yang ;sangat penting setelah untuk looo tanpa{}

Bahkan jika saya baru saja mengatakan kepada Anda bahwa jsperf bukan cara terbaik untuk menguji skrip .. saya menambahkan 2 loop ini di sini

http://jsperf.com/caching-array-length/40

Dan inilah jawaban lain tentang kinerja dalam javascript

https://stackoverflow.com/a/21353032/2450730

Jawaban ini adalah untuk menunjukkan cara-cara performant dalam menulis javascript. Jadi jika Anda tidak dapat membacanya, tanyakan dan Anda akan mendapatkan jawaban atau membaca buku tentang javascript http://www.ecma-international.org/ecma-262/5.1/

cocco
sumber
Jawaban ini dimulai dengan sangat baik . Saya perhatikan bahwa beberapa tahun terakhir forlebih cepat daripada while, dan saya pernah membaca di crome-dev itu persis karena alasan yang Anda sebutkan. Itu hanya masalah waktu sebelum whileakan menyusul lagi. Sejak saat itu, logika di bagian pertama dari jawaban Anda akan berlaku (sekali lagi, ya)! Namun implementasi modern tidak lagi kaku mengikuti setiap langkah yang ditentukan ecma (mereka mengoptimalkan). Karena sekarang mesin Anda bukan lagi leher botol yang paling mencolok, kini Anda dapat benar-benar menyadari bahwa cache-misses CPU dalam loop terbalik !
GitaarLAB
Jelaskan, jadi mungkin saya bisa memperbaiki jawabannya atau mempelajari sesuatu yang baru. tapi jawabannya sekarang lebih dari satu tahun ... browser mungkin telah berubah seiring waktu seperti yang selalu mereka lakukan ...
cocco
Menurut pendapat saya, while (--length) adalah evil karena sementara itu secara teknis bekerja karena 0 false, 0 dan false tidak benar-benar benar-benar sama secara semantik.
scott.korin
yeah ... ini postingan yang lebih lama sekarang ... tapi ya saya suka kesederhanaannya sementara. Dan pasti saat Anda menyebutkannya dalam kedua kasus, Anda harus tahu apa yang harus ditulis. Di sisi lain saya tidak pernah memiliki keharusan untuk mengulang melalui angka negatif.
cocco
9
"Mesin lebih suka ini" terdengar seperti kalimat dari iklan untuk deterjen cucian
CocoaBean
11

http://jsperf.com/caching-array-length/60

Revisi terbaru dari tes, yang saya siapkan (dengan menggunakan yang lama), menunjukkan satu hal.

Panjang cache tidak terlalu penting, tetapi tidak berbahaya.

Setiap pengujian pertama yang ditautkan di atas (pada tab yang baru dibuka) memberikan hasil terbaik untuk 4 cuplikan terakhir (bagan 3, 5, 7 dan 10) di Chrome, Opera dan Firefox di Debian Squeeze 64-bit ( perangkat keras desktop saya) ). Berjalan berikutnya memberikan hasil yang sangat berbeda.

Kesimpulan kinerja-bijaksana sederhana:

  • Pergilah dengan untuk loop (maju) dan tes menggunakan !==bukan <.
  • Jika Anda tidak harus menggunakan kembali array nanti, maka sementara loop pada decremented length dan destructive shift()-ing array juga efisien.

tl; dr

Saat ini (2011.10) di bawah pola terlihat menjadi yang tercepat.

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

Perlu diingat bahwa caching arr.lengthtidak penting di sini, jadi Anda bisa menguji i !== arr.lengthdan kinerjanya tidak turun, tetapi Anda akan mendapatkan kode yang lebih pendek.


PS: Saya tahu bahwa dalam cuplikan dengan shift()hasilnya dapat digunakan alih-alih mengakses elemen 0, tetapi saya entah bagaimana mengabaikannya setelah menggunakan revisi sebelumnya (yang salah ketika loop), dan kemudian saya tidak ingin kehilangan hasil yang sudah didapat.

przemoc
sumber
Membuat variabel insite loop seperti biarkan saat ini = arr [i] dapat mengurangi kinerja (alokasi memori besar)? Atau akan lebih baik untuk menyatakan arus sebelum loop? Atau gunakan arr [i] di semua tempat di dalam loop?
Makarov Sergey
8

"Terbaik" seperti dalam kinerja murni? atau kinerja DAN keterbacaan?

Kinerja murni "terbaik" adalah ini, yang menggunakan cache dan operator awalan ++ (data saya: http://jsperf.com/caching-array-length/189 )

for (var i = 0, len = myArray.length; i < len; ++i) {
  // blah blah
}

Saya berpendapat bahwa cache-less untuk-loop adalah keseimbangan terbaik dalam waktu eksekusi dan waktu membaca programmer. Setiap programmer yang memulai dengan C / C ++ / Java tidak akan menyia-nyiakan ms harus membaca yang ini

for(var i=0; i < arr.length; i++){
  // blah blah
}
valbaca
sumber
2
+1 untuk keterbacaan. Tidak peduli seberapa baik lennamanya, seseorang harus selalu melakukan pengambilan ganda pada loop pertama itu. Niat loop kedua jelas.
Josh Johnson
7

** cache panjang array di dalam loop, beberapa detik waktu akan dihilangkan. Tergantung pada item dalam array jika ada lebih banyak item dalam array ada perbedaan besar sehubungan dengan Ms waktu *

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**

Shushanth Pallegar
sumber
6

Ini tampaknya menjadi cara tercepat sejauh ini ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

Mempertimbangkan bahwa ini akan mengkonsumsi array, memakannya, dan tidak meninggalkan apa pun ...

Sergio
sumber
2
arr.shift();alih-alih arr.pop() agar array terbalik dapat dihindari.
Tintu C Raju
1
@Gargaroz jika Anda mendapatkan JSON dari layanan web misalnya layanan obrolan atau item pada katalog produk. Situasi lain ketika Anda hanya perlu menggunakan array sekali bisa misalnya bagan yang mendapat banyak koordinat pada basis intervall. Ada banyak contoh.
Sergio
Keren, terima kasih atas penjelasannya, Anda baik sekali; dapatkah Anda mengarahkan saya ke arah di mana saya dapat menemukan contoh lebih lanjut untuk mengeksploitasi loop semacam ini?
Gargaroz
1
Saat ini di Chrome 53 dan Firefox 48 itu adalah salah satu pendekatan yang paling lambat - periksa perfjs.info/array-iteration
Pencroff
1
@Alireza setuju, saya punya komentar untuk itu dalam jawaban saya juga.
Sergio
4

Ini tahun 2017 .

Saya melakukan beberapa tes.

https://jsperf.com/fastest-way-to-iterate-through-an-array/

Sepertinya while metode ini adalah yang tercepat di Chrome.

Tampak seperti penurunan kiri ( --i) jauh lebih cepat dari yang lain ( ++i, i--,i++ ) di Firefox.

Pendekatan ini adalah puasa rata-rata. Tapi iterates array dalam urutan terbalik.

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

Jika urutan ke depan penting, gunakan pendekatan ini.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}
SeregPie
sumber
3
Dengan menggunakan kata kunci, letAnda sebenarnya membandingkan kinerja pembuatan lingkup alih-alih kinerja loop. Menggunakan let i = 0, ii = array.lengthdalam forloop Anda akan membuat ruang lingkup baru untuk variabel-variabel di dalam forblok. whileContoh Anda tidak membuat ruang lingkup baru untuk variabel di dalam whileblok dan itu sebabnya mereka lebih cepat. Jika Anda menggunakan varalih-alih letdi dalam untuk loop, Anda akan melihat bagaimana loop masih secepat di 2017, tetapi lebih mudah dibaca.
CGodo
Berikut adalah jsperf dari apa yang saya bicarakan: jsperf.com/javascript-loop-testing-let-vs-var
CGodo
Ini hanya masalah di Chrome. Di Peramban lain vardan letmemiliki kinerja yang sama - stackoverflow.com/a/32345435/1785975
SeregPie
Menarik. Bagaimanapun, saya tidak menemukan pernyataan " whilelebih cepat di Chrome" akurat. Hanya jika menggunakan letkarena masalah kinerja kata kunci di Chrome. Jika menggunakan varatau dengan browser lain, fordan whilehampir sama, kadang for- kadang bahkan lebih cepat tergantung dari tolok ukur, dan itu lebih kompak dan mudah dibaca.
CGodo
2

Saya selalu menulis dengan gaya pertama.

Sekalipun kompiler cukup pintar untuk mengoptimalkannya untuk array, tapi tetap pintar jika kita menggunakan DOMNodeList di sini atau objek rumit dengan panjang yang dihitung?

Saya tahu apa pertanyaannya tentang array, tetapi saya pikir ini adalah praktik yang baik untuk menulis semua loop Anda dalam satu gaya.

Olegas
sumber
1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++ lebih cepat dari ++ i, --i dan i--

Anda juga dapat menyimpan baris terakhir dengan melakukan arr [i ++] terakhir kali Anda perlu mengakses i (tetapi ini bisa sulit untuk di-debug).

Anda dapat mengujinya di sini (dengan tes putaran lainnya): http://jsperf.com/for-vs-whilepop/5

Forestrf
sumber
1
Saat ini di Chrome 53 itu benar, tetapi Firefox 48 memiliki kecepatan yang sama - periksa perfjs.info/array-iteration
Pencroff
thunderguy.com/semicolon/2002/08/13/… mengatakan ++ilebih cepat ...
IMTheNachoMan
1

Pada September 2017 , tes jsperf ini menunjukkan pola berikut sebagai yang paling berkinerja di Chrome 60:

function foo(x) {
 x;
};
arr.forEach(foo);

Adakah yang bisa mereproduksi?

John Vandivier
sumber
Ya itu tampaknya tercepat, Namun coba jalankan ini di IE11 dan opsi-opsi itu adalah yang paling lambat. Dan di Firefox 55,03, 'lached cached cached len' mencapai 12mil, kinerja yang mengejutkan dibandingkan dengan 3.3k dari chrome. Agar konsisten dalam kinerja di semua browser, Anda harus menggunakan loop rata-rata tercepat untuk setiap browser.
Plippie
0

Saya telah mencoba beberapa cara lain untuk mengulangi array besar dan menemukan bahwa mengurangi separuh panjang array dan kemudian mengulangi kedua bagian dalam satu lingkaran lebih cepat. Perbedaan kinerja ini dapat dilihat saat memproses array besar .

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

Beberapa perbandingan kinerja (menggunakan timer.js) antara panjang cache untuk-loop VS metode di atas.

http://jsfiddle.net/tejzpr/bbLgzxgo/

tejzpr
sumber
0

Tes jsperf.com lain: http://jsperf.com/while-reverse-vs-for-cached-length

Loop sebaliknya sementara tampaknya menjadi yang tercepat. Satu-satunya masalah adalah bahwa sementara (--i) akan berhenti pada 0. Lalu bagaimana saya bisa mengakses array [0] di loop saya?

Moritz Schmitz v. Hülst
sumber
2
Jika Anda melakukannya while (i--)maka kejujuran iakan diuji sebelum menurunkan daripada mengurangi dan kemudian menguji kebenaran.
Justin Fisher
0

Sedangkan loop sedikit lebih cepat daripada untuk loop.

var len = arr.length;
while (len--) {
    // blah blah
}

Gunakan while loop sebagai gantinya

Azhar Zafar
sumber
-1

Solusi paling elegan yang saya tahu adalah menggunakan peta.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Dan
sumber
46
Pertanyaannya adalah tidak meminta cara paling lambat untuk iterate melalui loop
eoleary
-1

Coba ini:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
li bing zhao
sumber
-1

Cara tercepat untuk mengulang dalam array adalah dengan menggunakan filter. Metode filter () membuat array baru dengan semua elemen yang lulus tes diimplementasikan oleh fungsi yang disediakan.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

Dari pengalaman saya, saya selalu lebih suka filter, peta dll.

Rigin Oommen
sumber
Pertanyaannya adalah tentang pengulangan array dalam waktu singkat tidak menyalin array ke array baru.
Rahul Kadukar
-1

Pada 2019 WebWorker telah lebih populer, untuk dataset besar, kita dapat menggunakan WebWorker untuk memproses jauh lebih cepat dengan sepenuhnya memanfaatkan prosesor multi-core.

Kami juga memiliki Parallel.js yang membuat WebWorker lebih mudah digunakan untuk pemrosesan data.

Stackia
sumber