Saya melihat pertanyaan baru-baru ini di mana seseorang mengatakan itu kepada Anda, tetapi mereka hanya dimaksudkan untuk Array. Ini dianggap praktik buruk untuk iterasi melalui array tetapi tidak harus untuk iterasi melalui anggota suatu objek.
mmurch
19
Banyak jawaban dengan loop "for" seperti 'for (var i = 0; i <hColl.length; i ++) {}' dibandingkan dengan 'var i = hColl.length; sedangkan (i--) {} 'yang, ketika dimungkinkan untuk menggunakan bentuk yang terakhir itu jauh lebih cepat. Saya tahu ini tangensial tetapi saya pikir saya akan menambahkan sedikit ini.
Mark Schultheiss
2
@MarkSchultheiss tapi itu iterasi terbalik. Apakah ada versi iterasi maju yang lebih cepat?
ma11hew28
5
@Wynand gunakan var i = hCol1.length; for (i;i;i--;) {}cache i karena akan membuat perbedaan, dan menyederhanakan tes. - semakin tua peramban, semakin banyak perbedaan antara fordan whileSELALU cache penghitung "i" - dan tentu saja negatif tidak selalu cocok dengan situasinya, dan semakin negatif sementara obfuscate kode sedikit bagi sebagian orang. dan perhatikan var i = 1000; for (i; i; i--) {}dan var b =1000 for (b; b--;) {}kemana saya pergi 1000 ke 1 dan b pergi 999 ke 0. - semakin lama browser, semakin cenderung mendukung kinerja.
Mark Schultheiss
9
Anda juga bisa pintar. for(var i = 0, l = myArray.length; i < l; ++i) ...adalah yang tercepat dan terbaik yang bisa Anda dapatkan dengan iterasi maju.
Mathieu Amiot
Jawaban:
1557
Alasannya adalah bahwa satu konstruksi:
var a =[];// Create a new empty array.
a[5]=5;// Perfectly legal JavaScript that resizes the array.for(var i =0; i < a.length; i++){// Iterate over numeric indexes from 0 to 5, as everyone expects.
console.log(a[i]);}/* Will display:
undefined
undefined
undefined
undefined
undefined
5
*/
Juga pertimbangkan bahwa perpustakaan JavaScript mungkin melakukan hal-hal seperti ini, yang akan memengaruhi array apa pun yang Anda buat:
// Somewhere deep in your JavaScript library...Array.prototype.foo =1;// Now you have no idea what the below code will do.var a =[1,2,3,4,5];for(var x in a){// Now foo is a part of EVERY array and // will show up here as a value of 'x'.
console.log(x);}/* Will display:
0
1
2
3
4
foo
*/
Secara historis, beberapa browser bahkan mengulang lebih dari 'panjang', 'toString' dll!
bobince
398
Ingatlah untuk menggunakan (var x in a)daripada (x in a)- tidak ingin membuat global.
Chris Morgan
78
Masalah pertama bukan alasan itu buruk, hanya perbedaan dalam semantik. Masalah kedua menurut saya merupakan alasan (di atas bentrokan antara perpustakaan melakukan hal yang sama) bahwa mengubah prototipe dari datatype bawaan adalah buruk, daripada itu untuk..dalam buruk.
Stewart
86
@Stewart: Semua objek di JS asosiatif. Array JS adalah objek, jadi ya, itu asosiatif juga, tapi bukan itu gunanya. Jika Anda ingin mengulangi kunci objek , gunakan for (var key in object). Jika Anda ingin mengulangi elemen array , gunakan for(var i = 0; i < array.length; i += 1).
Martijn
42
Anda mengatakan untuk contoh pertama, bahwa itu Iterate atas indeks numerik dari 0 hingga 4, karena semua orang mengharapkan , saya berharap untuk beralih dari 0 hingga 5 ! Karena jika Anda menambahkan elemen di posisi 5, array akan memiliki 6 elemen (5 di antaranya tidak terdefinisi).
stivlo
393
The for-inPernyataan itu sendiri tidak "praktek buruk", namun dapat disalahgunakan , misalnya, untuk iterate lebih dari array atau array-seperti objek.
Tujuan dari for-inpernyataan ini adalah untuk menghitung lebih dari properti objek. Pernyataan ini akan muncul dalam rantai prototipe, juga menyebutkan sifat-sifat yang diwariskan , suatu hal yang terkadang tidak diinginkan.
Juga, urutan iterasi tidak dijamin oleh spec., Yang berarti bahwa jika Anda ingin "mengulangi" objek array, dengan pernyataan ini Anda tidak dapat yakin bahwa properti (indeks array) akan dikunjungi dalam urutan numerik.
Misalnya, dalam JScript (IE <= 8), urutan enumerasi bahkan pada objek Array didefinisikan ketika properti dibuat:
var array =[];
array[2]='c';
array[1]='b';
array[0]='a';for(var p in array){//... p will be "2", "1" and "0" on IE}
Juga, berbicara tentang properti yang diwarisi, jika Anda, misalnya, memperluas Array.prototypeobjek (seperti beberapa pustaka seperti yang dilakukan MooTools), properti itu juga akan disebutkan:
Array.prototype.last =function(){returnthis[this.length-1];};for(var p in []){// an empty array// last will be enumerated}
Seperti yang saya katakan sebelumnya untuk beralih pada array atau objek seperti array, hal terbaik adalah menggunakan loop berurutan , seperti plain-old for/ whileloop.
Saat Anda ingin menghitung hanya properti sendiri dari suatu objek (yang tidak diwariskan), Anda dapat menggunakan hasOwnPropertymetode ini:
for(var prop in obj){if(obj.hasOwnProperty(prop)){// prop is not inherited}}
Dan beberapa orang bahkan merekomendasikan untuk memanggil metode langsung dari Object.prototypeuntuk menghindari masalah jika seseorang menambahkan properti yang dinamai hasOwnPropertyke objek kita:
for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj, prop)){// prop is not inherited}}
Pertanyaan tentang poin terakhir tentang "hasOwnProperty": Jika seseorang menimpa "hasOwnProperty" pada suatu objek, Anda akan mengalami masalah. Tetapi bukankah Anda akan memiliki masalah yang sama jika seseorang menimpa "Object.prototype.hasOwnProperty"? Apa pun cara mereka mengacaukan Anda dan itu bukan tanggung jawab Anda, kan?
Scott Rippey
Anda bilang for..initu bukan praktik buruk, tapi bisa disalahgunakan. Sudahkah Anda mendapatkan contoh nyata praktik nyata yang baik di dunia, di mana Anda benar-benar ingin melihat semua properti objek termasuk properti yang diwarisi?
dengan jawaban ini saya menemukan bahwa dapat mengakses nilai denganfor (var p in array) { array[p]; }
equiman
117
Ada tiga alasan mengapa Anda tidak perlu menggunakannya for..inuntuk mengulangi elemen array:
for..inakan mengulang semua properti yang dimiliki dan diwarisi dari objek array yang tidak DontEnum; itu berarti jika seseorang menambahkan properti ke objek array tertentu (ada alasan yang valid untuk ini - saya sudah melakukannya sendiri) atau berubah Array.prototype(yang dianggap praktik buruk dalam kode yang seharusnya bekerja dengan baik dengan skrip lain), properti ini akan diulangi juga; properti yang diwarisi dapat dikecualikan dengan memeriksa hasOwnProperty(), tetapi itu tidak akan membantu Anda dengan properti yang diatur dalam objek array itu sendiri
for..in tidak dijamin untuk mempertahankan pemesanan elemen
itu lambat karena Anda harus berjalan semua properti objek array dan seluruh rantai prototipe dan masih hanya akan mendapatkan nama properti, yaitu untuk mendapatkan nilai, pencarian tambahan akan diperlukan
Karena untuk ... dalam penghitungan melalui objek yang menyimpan array, bukan array itu sendiri. Jika saya menambahkan fungsi ke rantai prototipe array, itu juga akan disertakan. Yaitu
Array.prototype.myOwnFunction =function(){ alert(this);}
a =newArray();
a[0]='foo';
a[1]='bar';for(x in a){
document.write(x +' = '+ a[x]);}
Ini akan menulis:
0 = foo
1 = bar
myOwnFunction = function () {alert (this); }
Dan karena Anda tidak pernah bisa yakin bahwa tidak ada yang akan ditambahkan ke rantai prototipe cukup gunakan for loop untuk menyebutkan array:
Array adalah Objects, tidak ada "objek yang menyimpan array".
RobG
41
Secara terpisah, tidak ada salahnya menggunakan for-in pada array. For-in iterates atas nama properti dari suatu objek, dan dalam kasus array "out-of-the-box", properti sesuai dengan indeks array. (Propertes bawaan suka length, toStringdan sebagainya tidak termasuk dalam iterasi.)
Namun, jika kode Anda (atau kerangka yang Anda gunakan) menambahkan properti kustom ke array atau ke prototipe array, maka properti ini akan dimasukkan dalam iterasi, yang mungkin bukan yang Anda inginkan.
Beberapa kerangka kerja JS, seperti Prototipe memodifikasi prototipe Array. Kerangka kerja lain seperti JQuery tidak, jadi dengan JQuery Anda dapat menggunakan for-in dengan aman.
Jika Anda ragu, Anda sebaiknya tidak menggunakan for-in.
Cara alternatif untuk iterasi melalui array menggunakan for-loop:
for(var ix=0;ix<arr.length;ix++) alert(ix);
Namun, ini memiliki masalah yang berbeda. Masalahnya adalah bahwa array JavaScript dapat memiliki "lubang". Jika Anda mendefinisikan arrsebagai:
var arr =["hello"];
arr[100]="goodbye";
Kemudian array memiliki dua item, tetapi panjang 101. Menggunakan for-in akan menghasilkan dua indeks, sedangkan for-loop akan menghasilkan 101 indeks, di mana 99 memiliki nilai undefined.
Jawaban yang lebih panjang: Itu tidak layak, bahkan jika urutan elemen berurutan dan kinerja optimal tidak diperlukan.
Jawaban panjang: Tidak layak ...
Menggunakan for (var property in array)akan menyebabkan arrayuntuk diiterasi sebagai objek , melintasi rantai prototipe objek dan akhirnya melakukan lebih lambat daripada berbasis indeksfor loop .
for (... in ...) tidak dijamin untuk mengembalikan properti objek dalam urutan berurutan, seperti yang mungkin diharapkan.
Menggunakan hasOwnProperty()dan !isNaN()memeriksa untuk menyaring properti objek adalah overhead tambahan yang menyebabkannya bekerja lebih lambat dan meniadakan alasan utama untuk menggunakannya di tempat pertama, yaitu karena format yang lebih ringkas.
Untuk alasan ini, trade-off yang dapat diterima antara kinerja dan kenyamanan bahkan tidak ada. Benar-benar tidak ada manfaat kecuali tujuannya adalah untuk menangani array sebagai objek dan melakukan operasi pada properti objek array.
Selain alasan yang diberikan dalam jawaban lain, Anda mungkin tidak ingin menggunakan struktur "untuk ... dalam" jika Anda perlu melakukan matematika dengan variabel penghitung karena loop berulang melalui nama properti objek dan variabel tersebut adalah sebuah string.
Anda dapat menggunakan awalan +alih-alih parseIntkecuali Anda benar-benar membutuhkan integer atau mengabaikan karakter yang tidak valid.
Konrad Borowski
Juga, menggunakan parseInt()tidak dianjurkan. Coba parseInt("025");dan itu akan gagal.
Derek 朕 會 功夫
6
@Derek 朕 會 功夫 - Anda pasti bisa menggunakan parseInt. Masalahnya adalah jika Anda tidak memasukkan radix, browser yang lebih lama mungkin mencoba menginterpretasikan angka (sehingga 025 menjadi oktal). Ini diperbaiki dalam ECMAScript 5 tetapi masih terjadi untuk angka yang dimulai dengan "0x" (itu menafsirkan angka sebagai hex). Untuk berada di sisi yang aman, gunakan radix untuk menentukan nomor seperti parseInt("025", 10)- yang menentukan basis 10.
Mekanika dan urutan penghitungan properti ... tidak ditentukan ...
(Penekanan milikku.)
Itu berarti jika suatu browser ingin, itu bisa melalui properti dalam urutan di mana mereka dimasukkan. Atau dalam urutan numerik. Atau dalam urutan leksikal (di mana "30" muncul sebelum "4"! Ingat semua kunci objek - dan dengan demikian, semua indeks array - sebenarnya adalah string, sehingga masuk akal secara total). Itu bisa melalui mereka dengan ember, jika mengimplementasikan objek sebagai tabel hash. Atau ambil salah satu dari itu dan tambahkan "mundur". Peramban bahkan dapat beralih secara acak dan memenuhi persyaratan ECMA-262, asalkan mengunjungi setiap properti tepat satu kali.
Dalam praktiknya, sebagian besar browser saat ini ingin beralih dalam urutan yang kurang lebih sama. Tapi tidak ada yang mengatakan mereka harus melakukannya. Itu implementasi spesifik, dan bisa berubah kapan saja jika cara lain ditemukan jauh lebih efisien.
Either way, for... indisertai dengan itu tidak ada konotasi ketertiban. Jika Anda peduli tentang pesanan, jelaskan tentang hal itu dan gunakan forloop reguler dengan indeks.
Seperti yang dikatakan orang lain, Anda mungkin mendapatkan kunci yang tidak ada dalam array Anda atau yang diwarisi dari prototipe. Jadi jika, katakanlah, perpustakaan menambahkan properti ke prototipe Array atau Object:
Array.prototype.someProperty =true
Anda akan mendapatkannya sebagai bagian dari setiap larik:
for(var item in [1,2,3]){
console.log(item)// will log 1,2,3 but also "someProperty"}
Anda bisa menyelesaikan ini dengan metode hasOwnProperty:
var ary =[1,2,3];for(var item in ary){if(ary.hasOwnProperty(item)){
console.log(item)// will log only 1,2,3}}
tapi ini berlaku untuk iterasi atas objek apa pun dengan loop for-in.
Dua
Biasanya urutan item dalam array adalah penting, tetapi loop for-in tidak harus berulang dalam urutan yang benar, itu karena ia memperlakukan array sebagai objek, yang merupakan cara penerapannya dalam JS, dan tidak sebagai sebuah array. Ini sepertinya hal kecil, tetapi benar-benar dapat mengacaukan aplikasi dan sulit untuk di-debug.
Object.keys(a).forEach( function(item) { console.log(item) } )beralih di atas array kunci properti sendiri, bukan yang diwarisi dari prototipe.
Qwerty
2
Benar, tetapi seperti for-in loop, itu tidak selalu berada dalam urutan indeks yang benar. Juga, itu tidak akan berfungsi pada browser lama yang tidak mendukung ES5.
Di firefox 3 Anda juga bisa menggunakan arr.forEach atau untuk (var [i, v] di Iterator (arr)) {} tetapi tidak ada yang bekerja di IE, meskipun Anda bisa menulis sendiri metode forEach.
vava
dan hampir setiap perpustakaan memiliki metode sendiri untuk ini juga.
vava
5
Jawaban ini salah. "Panjang" tidak akan termasuk dalam iterasi untuk-dalam. Hanya properti yang Anda tambahkan sendiri yang disertakan.
JacquesB
16
Saya rasa saya tidak punya banyak hal untuk ditambahkan misalnya. Jawaban Triptych atau jawaban CMS tentang mengapa menggunakanfor...in harus dihindari dalam beberapa kasus.
Namun, saya ingin menambahkan bahwa di browser modern ada alternatif for...inyang dapat digunakan dalam kasus-kasus di mana for...intidak dapat digunakan. Alternatif itu adalah for...of:
for(var item of items){
console.log(item);}
Catatan :
Sayangnya, tidak ada versi Internet Explorer yang mendukung for...of( Edge 12+ melakukannya), jadi Anda harus menunggu sedikit lebih lama hingga Anda dapat menggunakannya dalam kode produksi sisi klien Anda. Namun, aman untuk digunakan di kode JS sisi server Anda (jika Anda menggunakan Node.js ).
Masalah dengan for ... in ...- dan ini hanya menjadi masalah ketika seorang programmer tidak benar-benar mengerti bahasa; itu bukan benar-benar bug atau apa pun - adalah bahwa itu berulang atas semua anggota objek (well, semua anggota enumerable , tapi itu detail untuk saat ini). Ketika Anda ingin beralih hanya pada properti yang diindeks dari array, satu-satunya cara dijamin untuk menjaga hal-hal konsisten secara semantik adalah dengan menggunakan indeks integer (yaitu, for (var i = 0; i < array.length; ++i)loop gaya).
Objek apa pun dapat memiliki sifat sewenang-wenang yang terkait dengannya. Tidak ada yang buruk tentang memuat properti tambahan ke instance array, khususnya. Kode yang ingin melihat hanya properti seperti array yang diindeks karena itu harus tetap berpegang pada indeks integer. Kode yang sepenuhnya menyadari apa yang perlufor ... in dan benar-benar perlu untuk melihat semua properti, baik maka itu juga ok.
Penjelasan bagus Pointy. Hanya penasaran. Jika saya memiliki array yang ada di dalam objek di bawah properti multiply dan apakah for in, dibandingkan dengan reguler untuk loop, array tersebut akan diulang? (yang pada intinya, kinerja lambat, kan?)
NiCk Newman
2
@NiCkNewman juga objek yang Anda referensi setelah indalam satu for ... inlingkaran hanya akan
Runcing
Saya melihat. Hanya ingin tahu karena saya memiliki objek dan array di dalam objek permainan utama saya dan bertanya-tanya apakah untuk inning itu akan lebih menyakitkan maka cukup biasa untuk loop pada indeks.
NiCk Newman
@NiCkNewman baik tema dari seluruh pertanyaan ini adalah bahwa Anda tidak boleh menggunakan for ... inpada array; ada banyak alasan bagus untuk tidak melakukannya. Ini bukan masalah kinerja seperti masalah "pastikan tidak rusak".
Runcing
Nah, objek saya disimpan dalam array secara teknis, itu sebabnya saya khawatir, sesuatu seperti [{a:'hey',b:'hi'},{a:'hey',b:'hi'}]:, tapi ya, saya mengerti.
NiCk Newman
9
Juga, karena semantik, cara for, inmemperlakukan array (yaitu sama dengan objek JavaScript lainnya) tidak selaras dengan bahasa populer lainnya.
// C#char[] a =newchar[]{'A','B','C'};
foreach (char x in a)System.Console.Write(x);//Output: "ABC"// Javachar[] a ={'A','B','C'};for(char x : a)System.out.print(x);//Output: "ABC"// PHP
$a = array('A','B','C');
foreach ($a as $x) echo $x;//Output: "ABC"// JavaScriptvar a =['A','B','C'];for(var x in a) document.write(x);//Output: "012"
TL&DR: Menggunakan for inloop dalam array bukanlah kejahatan, pada kenyataannya justru sebaliknya.
Saya pikir for inloop adalah permata dari JS jika digunakan dengan benar dalam array. Anda diharapkan memiliki kontrol penuh atas perangkat lunak Anda dan tahu apa yang Anda lakukan. Mari kita lihat kekurangan yang disebutkan dan buktikan satu per satu.
Itu loop melalui properti yang diwarisi juga: Pertama-tama semua ekstensi ke yang Array.prototypeseharusnya telah dilakukan dengan menggunakan Object.defineProperty()dan enumerabledeskriptor mereka harus diatur ke false. Pustaka yang tidak melakukannya tidak boleh digunakan sama sekali.
Properti-properti yang Anda tambahkan ke rantai warisan kemudian mendapatkan dihitung: Ketika melakukan berbagai sub-mengklasifikasikan oleh Object.setPrototypeOfatau dengan Kelas extend. Anda harus menggunakan lagi Object.defineProperty()yang secara default mengatur writable, enumerabledan configurabledeskriptor properti false. Mari kita lihat contoh sub-klasifikasi array di sini ...
functionStack(...a){var stack =newArray(...a);Object.setPrototypeOf(stack,Stack.prototype);return stack;}Stack.prototype =Object.create(Array.prototype);// now stack has full access to array methods.Object.defineProperty(Stack.prototype,"constructor",{value:Stack});// now Stack is a proper constructorObject.defineProperty(Stack.prototype,"peak",{value:function(){// add Stack "only" methods to the Stack.prototype.returnthis[this.length-1];}});var s =newStack(1,2,3,4,1);
console.log(s.peak());
s[s.length]=7;
console.log("length:",s.length);
s.push(42);
console.log(JSON.stringify(s));
console.log("length:",s.length);for(var i in s) console.log(s[i]);
Jadi Anda tahu .. for inloop sekarang aman karena Anda peduli dengan kode Anda.
The for inLoop lambat: Hell no. Ini sejauh ini metode iterasi tercepat jika Anda mengulang array jarang yang diperlukan dari waktu ke waktu. Ini adalah salah satu trik kinerja paling penting yang harus diketahui. Mari kita lihat sebuah contoh. Kami akan mengulangi array yang jarang.
var a =[];
a[0]="zero";
a[10000000]="ten million";
console.time("for loop on array a:");for(var i=0; i < a.length; i++) a[i]&& console.log(a[i]);
console.timeEnd("for loop on array a:");
console.time("for in loop on array a:");for(var i in a) a[i]&& console.log(a[i]);
console.timeEnd("for in loop on array a:");
Pengaturan pembandingan @Ravi Shanker Reddy Good. Seperti yang telah saya sebutkan dalam jawaban saya, for inloop mengungguli yang lain "jika" array jarang dan semakin banyak jika semakin besar ukurannya. Jadi saya telah mengatur ulang tes bangku untuk array jarang arr,, dari ukuran ~ 10.000 dengan hanya 50 item yang dipilih secara [42,"test",{t:1},null, void 0]acak di antara indeks acak. Anda akan segera melihat perbedaannya. - >> Periksa di sini << - .
Redu
8
Selain masalah lain, sintaks "for..in" mungkin lebih lambat, karena indeksnya adalah string, bukan bilangan bulat.
var a =["a"]for(var i in a)
alert(typeof i)// 'string'for(var i =0; i < a.length; i++)
alert(typeof i)// 'number'
Mungkin tidak terlalu penting. Elemen array adalah properti dari objek berbasis Array atau seperti Array, dan semua properti objek memiliki kunci string. Kecuali jika mesin JS Anda mengoptimalkannya, bahkan jika Anda menggunakan nomor, akhirnya akan diubah menjadi string untuk pencarian.
cHao
Terlepas dari masalah kinerja apa pun, jika Anda baru mengenal JavaScript, gunakan var i in adan perkirakan indeksnya adalah bilangan bulat, maka melakukan sesuatu seperti a[i+offset] = <value>akan meletakkan nilai di tempat yang sepenuhnya salah. ("1" + 1 == "11").
szmoore
8
Aspek penting adalah bahwa for...inhanya iterate atas properti yang terkandung dalam objek yang atribut enumerable properti mereka disetel ke true. Jadi, jika seseorang mencoba untuk mengulangi objek menggunakan for...inmaka properti sewenang-wenang dapat dilewatkan jika atribut properti enumerable mereka salah. Sangat mungkin untuk mengubah atribut properti enumerable untuk objek Array normal sehingga elemen-elemen tertentu tidak disebutkan. Meskipun secara umum atribut properti cenderung berlaku untuk fungsi properti dalam suatu objek.
Orang dapat memeriksa nilai atribut properti enumerable properti dengan:
Ini adalah fitur yang tersedia di ECMAScript 5 - dalam versi sebelumnya tidak mungkin mengubah nilai atribut properti enumerable (selalu disetel ke true).
The for/ inbekerja dengan dua jenis variabel: hashtable (array asosiatif) dan array (non-asosiatif).
JavaScript akan secara otomatis menentukan cara barang tersebut melewati item. Jadi, jika Anda tahu bahwa array Anda benar-benar non-asosiatif, Anda dapat menggunakan for (var i=0; i<=arrayLen; i++), dan melewatkan iterasi deteksi otomatis.
Tetapi menurut saya, lebih baik menggunakan for/ in, proses yang diperlukan untuk deteksi otomatis itu sangat kecil.
Jawaban nyata untuk ini akan tergantung pada bagaimana parser / penterjemah kode JavaScript. Itu dapat berubah di antara browser.
Saya tidak dapat memikirkan tujuan lain untuk tidak menggunakan for/ in;
//Non-associativevar arr =['a','b','c'];for(var i in arr)
alert(arr[i]);//Associativevar arr ={
item1 :'a',
item2 :'b',
item3 :'c'};for(var i in arr)
alert(arr[i]);
Tidak cukup - tidak apa-apa untuk menambahkan properti yang diberi nama arbitrer ke instance array, dan itu akan diuji truedari hasOwnProperty()cek.
Runcing
Poin bagus, terima kasih. Aku tidak pernah sebodoh itu untuk melakukan itu pada Array sendiri, jadi aku belum mempertimbangkan itu!
JAL
1
@Pointy Saya belum menguji ini, tapi mungkin ini bisa diatasi dengan menggunakan isNaNcek pada setiap nama properti.
WynandB
1
@ Menangkan ide yang menarik; Namun saya tidak benar-benar melihat mengapa itu sepadan dengan masalah ketika iterasi dengan indeks numerik sederhana sangat mudah.
Runcing
@ WynandB maaf untuk benjolan, tapi saya merasa ada koreksi: isNaNuntuk memeriksa apakah suatu variabel adalah nilai khusus NaN atau tidak, itu tidak dapat digunakan untuk memeriksa 'hal-hal selain angka' (Anda dapat menggunakan reguler typeof untuk itu).
doldt
6
Ini tidak selalu buruk (berdasarkan apa yang Anda lakukan), tetapi dalam kasus array, jika sesuatu telah ditambahkan Array.prototype, maka Anda akan mendapatkan hasil yang aneh. Di mana Anda mengharapkan loop ini berjalan tiga kali:
var arr =['a','b','c'];for(var key in arr){...}
Jika fungsi yang disebut helpfulUtilityMethodtelah ditambahkan ke Array's prototype, maka loop Anda akan berakhir berjalan empat kali: keyakan 0, 1, 2, dan helpfulUtilityMethod. Jika Anda hanya mengharapkan bilangan bulat, oops.
Hanya catatan tentang SO - tidak ada 'di atas' karena komentar mengubah urutan halaman setiap saat. Jadi, kami tidak benar-benar tahu komentar yang Anda maksud. Adalah baik untuk mengatakan "dalam komentar x orang" karena alasan ini.
JAL
@ JAL ... atau tambahkan tautan permanen ke jawabannya.
WynandB
5
Menggunakan for...inloop untuk sebuah array tidak salah, walaupun saya bisa menebak mengapa seseorang memberi tahu Anda bahwa:
1.) Sudah ada fungsi orde yang lebih tinggi, atau metode, yang memiliki tujuan untuk array, tetapi memiliki lebih banyak fungsi dan sintaks yang lebih ramping, yang disebut 'forEach': Array.prototype.forEach(function(element, index, array) {} );
2.) Array selalu memiliki panjang, tetapi for...indan forEachtidak menjalankan fungsi untuk nilai apa pun 'undefined', hanya untuk indeks yang memiliki nilai yang ditentukan. Jadi jika Anda hanya menetapkan satu nilai, loop ini hanya akan mengeksekusi fungsi sekali, tetapi karena array dihitung, itu akan selalu memiliki panjang hingga indeks tertinggi yang memiliki nilai yang ditentukan, tetapi panjang itu bisa luput dari perhatian ketika menggunakan ini loop.
3.) Standar untuk loop akan menjalankan fungsi sebanyak yang Anda tentukan dalam parameter, dan karena array diberi nomor, lebih masuk akal untuk menentukan berapa kali Anda ingin menjalankan suatu fungsi. Tidak seperti loop lainnya, loop for kemudian dapat menjalankan fungsi untuk setiap indeks dalam array, apakah nilainya didefinisikan atau tidak.
Intinya, Anda bisa menggunakan loop apa saja, tetapi Anda harus ingat persis cara kerjanya. Memahami kondisi di mana loop berbeda mengulangi, fungsi terpisah mereka, dan menyadari bahwa mereka akan lebih atau kurang sesuai untuk skenario yang berbeda.
Juga, mungkin dianggap sebagai praktik yang lebih baik untuk menggunakan forEachmetode ini daripada for...inloop pada umumnya, karena lebih mudah untuk menulis dan memiliki lebih banyak fungsi, jadi Anda mungkin ingin membiasakan diri hanya menggunakan metode dan standar ini untuk, tetapi Anda panggilan.
Lihat di bawah ini bahwa dua loop pertama hanya menjalankan pernyataan console.log sekali, sedangkan standar untuk loop mengeksekusi fungsi sebanyak yang ditentukan, dalam hal ini, array.length = 6.
var arr =[];
arr[5]='F';for(var index in arr){
console.log(index);
console.log(arr[index]);
console.log(arr)}// 5// 'F'// => (6) [undefined x 5, 6]
arr.forEach(function(element, index, arr){
console.log(index);
console.log(element);
console.log(arr);});// 5// 'F'// => Array (6) [undefined x 5, 6]for(var index =0; index < arr.length; index++){
console.log(index);
console.log(arr[index]);
console.log(arr);};// 0// undefined// => Array (6) [undefined x 5, 6]// 1// undefined// => Array (6) [undefined x 5, 6]// 2// undefined// => Array (6) [undefined x 5, 6]// 3// undefined// => Array (6) [undefined x 5, 6]// 4// undefined// => Array (6) [undefined x 5, 6]// 5// 'F'// => Array (6) [undefined x 5, 6]
Berikut adalah alasan mengapa ini (biasanya) merupakan praktik buruk:
for...inloop mengulangi semua properti enumerable mereka sendiri dan properti enumerable prototipe mereka. Biasanya dalam iterasi array kita hanya ingin mengulangi array itu sendiri. Dan meskipun Anda sendiri mungkin tidak menambahkan apa pun ke array, pustaka atau kerangka kerja Anda mungkin menambahkan sesuatu.
Contoh :
Array.prototype.hithere ='hithere';var array =[1,2,3];for(let el in array){// the hithere property will also be iterated over
console.log(el);}
for...inloop tidak menjamin urutan iterasi tertentu . Meskipun pesanan biasanya terlihat di sebagian besar browser modern hari ini, masih belum ada jaminan 100%.
for...inloop mengabaikan undefinedelemen array, yaitu elemen array yang belum ditetapkan.
Contoh ::
const arr =[];
arr[3]='foo';// resize the array to 4
arr[4]=undefined;// add another element with value undefined to it// iterate over the array, a for loop does show the undefined elementsfor(let i =0; i < arr.length; i++){
console.log(arr[i]);}
console.log('\n');// for in does ignore the undefined elementsfor(let el in arr){
console.log(arr[el]);}
untuk ... di berguna ketika bekerja pada objek dalam JavaScript, tetapi tidak untuk Array, tapi tetap saja kita tidak bisa mengatakan itu cara yang salah, tetapi tidak disarankan, lihat contoh di bawah ini menggunakan for ... in loop:
let txt ="";const person ={fname:"Alireza", lname:"Dezfoolian", age:35};for(const x in person){
txt += person[x]+" ";}
console.log(txt);//Alireza Dezfoolian 35
OK, mari kita lakukan dengan Array sekarang:
let txt ="";const person =["Alireza","Dezfoolian",35];for(const x in person){
txt += person[x]+" ";}
console.log(txt);//Alireza Dezfoolian 35
Seperti yang Anda lihat hasilnya sama ...
Tapi mari kita coba sesuatu, mari kita prototipe sesuatu ke Array ...
Array.prototype.someoneelse ="someoneelse";
Sekarang kita membuat Array baru ();
let txt ="";const arr =newArray();
arr[0]='Alireza';
arr[1]='Dezfoolian';
arr[2]=35;for(x in arr){
txt += arr[x]+" ";}
console.log(txt);//Alireza Dezfoolian 35 someoneelse
Kalian lihat seseorang itu sendiri !!! ... Kita benar-benar mengulang-ulang objek Array baru dalam kasus ini!
Jadi itulah salah satu alasan mengapa kita perlu menggunakan untuk..dalam hati-hati, tapi itu tidak selalu terjadi ...
Karena elemen JavaScript disimpan sebagai properti objek standar, tidak disarankan untuk mengulanginya menggunakan array JavaScript yang digunakan untuk ... dalam loop karena elemen normal dan semua properti yang dapat dihitung akan dicantumkan.
walaupun tidak secara khusus ditanggapi oleh pertanyaan ini, saya akan menambahkan bahwa ada alasan yang sangat baik untuk tidak pernah menggunakan ... dengan NodeList(karena orang akan mendapatkan dari querySelectorAllpanggilan, karena tidak melihat elemen yang dikembalikan sama sekali, sebagai gantinya hanya mengulangi properti NodeList.
var i = hCol1.length; for (i;i;i--;) {}
cache i karena akan membuat perbedaan, dan menyederhanakan tes. - semakin tua peramban, semakin banyak perbedaan antarafor
danwhile
SELALU cache penghitung "i" - dan tentu saja negatif tidak selalu cocok dengan situasinya, dan semakin negatif sementaraobfuscate
kode sedikit bagi sebagian orang. dan perhatikanvar i = 1000; for (i; i; i--) {}
danvar b =1000 for (b; b--;) {}
kemana saya pergi 1000 ke 1 dan b pergi 999 ke 0. - semakin lama browser, semakin cenderung mendukung kinerja.for(var i = 0, l = myArray.length; i < l; ++i) ...
adalah yang tercepat dan terbaik yang bisa Anda dapatkan dengan iterasi maju.Jawaban:
Alasannya adalah bahwa satu konstruksi:
kadang-kadang bisa sangat berbeda dari yang lain:
Juga pertimbangkan bahwa perpustakaan JavaScript mungkin melakukan hal-hal seperti ini, yang akan memengaruhi array apa pun yang Anda buat:
sumber
(var x in a)
daripada(x in a)
- tidak ingin membuat global.for (var key in object)
. Jika Anda ingin mengulangi elemen array , gunakanfor(var i = 0; i < array.length; i += 1)
.The
for-in
Pernyataan itu sendiri tidak "praktek buruk", namun dapat disalahgunakan , misalnya, untuk iterate lebih dari array atau array-seperti objek.Tujuan dari
for-in
pernyataan ini adalah untuk menghitung lebih dari properti objek. Pernyataan ini akan muncul dalam rantai prototipe, juga menyebutkan sifat-sifat yang diwariskan , suatu hal yang terkadang tidak diinginkan.Juga, urutan iterasi tidak dijamin oleh spec., Yang berarti bahwa jika Anda ingin "mengulangi" objek array, dengan pernyataan ini Anda tidak dapat yakin bahwa properti (indeks array) akan dikunjungi dalam urutan numerik.
Misalnya, dalam JScript (IE <= 8), urutan enumerasi bahkan pada objek Array didefinisikan ketika properti dibuat:
Juga, berbicara tentang properti yang diwarisi, jika Anda, misalnya, memperluas
Array.prototype
objek (seperti beberapa pustaka seperti yang dilakukan MooTools), properti itu juga akan disebutkan:Seperti yang saya katakan sebelumnya untuk beralih pada array atau objek seperti array, hal terbaik adalah menggunakan loop berurutan , seperti plain-old
for
/while
loop.Saat Anda ingin menghitung hanya properti sendiri dari suatu objek (yang tidak diwariskan), Anda dapat menggunakan
hasOwnProperty
metode ini:Dan beberapa orang bahkan merekomendasikan untuk memanggil metode langsung dari
Object.prototype
untuk menghindari masalah jika seseorang menambahkan properti yang dinamaihasOwnProperty
ke objek kita:sumber
for..in
jauh lebih lambat daripada loop "normal".for..in
itu bukan praktik buruk, tapi bisa disalahgunakan. Sudahkah Anda mendapatkan contoh nyata praktik nyata yang baik di dunia, di mana Anda benar-benar ingin melihat semua properti objek termasuk properti yang diwarisi?for (var p in array) { array[p]; }
Ada tiga alasan mengapa Anda tidak perlu menggunakannya
for..in
untuk mengulangi elemen array:for..in
akan mengulang semua properti yang dimiliki dan diwarisi dari objek array yang tidakDontEnum
; itu berarti jika seseorang menambahkan properti ke objek array tertentu (ada alasan yang valid untuk ini - saya sudah melakukannya sendiri) atau berubahArray.prototype
(yang dianggap praktik buruk dalam kode yang seharusnya bekerja dengan baik dengan skrip lain), properti ini akan diulangi juga; properti yang diwarisi dapat dikecualikan dengan memeriksahasOwnProperty()
, tetapi itu tidak akan membantu Anda dengan properti yang diatur dalam objek array itu sendirifor..in
tidak dijamin untuk mempertahankan pemesanan elemenitu lambat karena Anda harus berjalan semua properti objek array dan seluruh rantai prototipe dan masih hanya akan mendapatkan nama properti, yaitu untuk mendapatkan nilai, pencarian tambahan akan diperlukan
sumber
Karena untuk ... dalam penghitungan melalui objek yang menyimpan array, bukan array itu sendiri. Jika saya menambahkan fungsi ke rantai prototipe array, itu juga akan disertakan. Yaitu
Ini akan menulis:
Dan karena Anda tidak pernah bisa yakin bahwa tidak ada yang akan ditambahkan ke rantai prototipe cukup gunakan for loop untuk menyebutkan array:
Ini akan menulis:
sumber
Secara terpisah, tidak ada salahnya menggunakan for-in pada array. For-in iterates atas nama properti dari suatu objek, dan dalam kasus array "out-of-the-box", properti sesuai dengan indeks array. (Propertes bawaan suka
length
,toString
dan sebagainya tidak termasuk dalam iterasi.)Namun, jika kode Anda (atau kerangka yang Anda gunakan) menambahkan properti kustom ke array atau ke prototipe array, maka properti ini akan dimasukkan dalam iterasi, yang mungkin bukan yang Anda inginkan.
Beberapa kerangka kerja JS, seperti Prototipe memodifikasi prototipe Array. Kerangka kerja lain seperti JQuery tidak, jadi dengan JQuery Anda dapat menggunakan for-in dengan aman.
Jika Anda ragu, Anda sebaiknya tidak menggunakan for-in.
Cara alternatif untuk iterasi melalui array menggunakan for-loop:
Namun, ini memiliki masalah yang berbeda. Masalahnya adalah bahwa array JavaScript dapat memiliki "lubang". Jika Anda mendefinisikan
arr
sebagai:Kemudian array memiliki dua item, tetapi panjang 101. Menggunakan for-in akan menghasilkan dua indeks, sedangkan for-loop akan menghasilkan 101 indeks, di mana 99 memiliki nilai
undefined
.sumber
Pada 2016 (ES6) kita dapat menggunakan
for…of
untuk iterasi array, seperti yang sudah diperhatikan oleh John Slegers.Saya hanya ingin menambahkan kode demonstrasi sederhana ini, untuk membuatnya lebih jelas:
Konsol menunjukkan:
Dengan kata lain:
for...of
dihitung dari 0 hingga 5, dan juga diabaikanArray.prototype.foo
. Ini menunjukkan nilai array .for...in
hanya mencantumkan5
, mengabaikan indeks array yang tidak ditentukan, tetapi menambahkanfoo
. Ini menunjukkan nama properti array .sumber
Jawaban singkat: Itu tidak layak.
Jawaban yang lebih panjang: Itu tidak layak, bahkan jika urutan elemen berurutan dan kinerja optimal tidak diperlukan.
Jawaban panjang: Tidak layak ...
for (var property in array)
akan menyebabkanarray
untuk diiterasi sebagai objek , melintasi rantai prototipe objek dan akhirnya melakukan lebih lambat daripada berbasis indeksfor
loop .for (... in ...)
tidak dijamin untuk mengembalikan properti objek dalam urutan berurutan, seperti yang mungkin diharapkan.hasOwnProperty()
dan!isNaN()
memeriksa untuk menyaring properti objek adalah overhead tambahan yang menyebabkannya bekerja lebih lambat dan meniadakan alasan utama untuk menggunakannya di tempat pertama, yaitu karena format yang lebih ringkas.Untuk alasan ini, trade-off yang dapat diterima antara kinerja dan kenyamanan bahkan tidak ada. Benar-benar tidak ada manfaat kecuali tujuannya adalah untuk menangani array sebagai objek dan melakukan operasi pada properti objek array.
sumber
Selain alasan yang diberikan dalam jawaban lain, Anda mungkin tidak ingin menggunakan struktur "untuk ... dalam" jika Anda perlu melakukan matematika dengan variabel penghitung karena loop berulang melalui nama properti objek dan variabel tersebut adalah sebuah string.
Sebagai contoh,
akan menulis
sedangkan,
akan menulis
Tentu saja, ini dapat dengan mudah diatasi dengan memasukkan
dalam lingkaran, tetapi struktur pertama lebih langsung.
sumber
+
alih-alihparseInt
kecuali Anda benar-benar membutuhkan integer atau mengabaikan karakter yang tidak valid.parseInt()
tidak dianjurkan. CobaparseInt("025");
dan itu akan gagal.parseInt
. Masalahnya adalah jika Anda tidak memasukkan radix, browser yang lebih lama mungkin mencoba menginterpretasikan angka (sehingga 025 menjadi oktal). Ini diperbaiki dalam ECMAScript 5 tetapi masih terjadi untuk angka yang dimulai dengan "0x" (itu menafsirkan angka sebagai hex). Untuk berada di sisi yang aman, gunakan radix untuk menentukan nomor sepertiparseInt("025", 10)
- yang menentukan basis 10.Selain dari fakta bahwa
for
...in
loop atas semua properti yang dapat dihitung (yang tidak sama dengan "semua elemen array"!), Lihat http://www.ecma-international.org/publications/files/ECMA-ST/Ecma -262.pdf , bagian 12.6.4 (edisi ke-5) atau 13.7.5.15 (edisi ke-7):(Penekanan milikku.)
Itu berarti jika suatu browser ingin, itu bisa melalui properti dalam urutan di mana mereka dimasukkan. Atau dalam urutan numerik. Atau dalam urutan leksikal (di mana "30" muncul sebelum "4"! Ingat semua kunci objek - dan dengan demikian, semua indeks array - sebenarnya adalah string, sehingga masuk akal secara total). Itu bisa melalui mereka dengan ember, jika mengimplementasikan objek sebagai tabel hash. Atau ambil salah satu dari itu dan tambahkan "mundur". Peramban bahkan dapat beralih secara acak dan memenuhi persyaratan ECMA-262, asalkan mengunjungi setiap properti tepat satu kali.
Dalam praktiknya, sebagian besar browser saat ini ingin beralih dalam urutan yang kurang lebih sama. Tapi tidak ada yang mengatakan mereka harus melakukannya. Itu implementasi spesifik, dan bisa berubah kapan saja jika cara lain ditemukan jauh lebih efisien.
Either way,
for
...in
disertai dengan itu tidak ada konotasi ketertiban. Jika Anda peduli tentang pesanan, jelaskan tentang hal itu dan gunakanfor
loop reguler dengan indeks.sumber
Terutama dua alasan:
Satu
Seperti yang dikatakan orang lain, Anda mungkin mendapatkan kunci yang tidak ada dalam array Anda atau yang diwarisi dari prototipe. Jadi jika, katakanlah, perpustakaan menambahkan properti ke prototipe Array atau Object:
Anda akan mendapatkannya sebagai bagian dari setiap larik:
Anda bisa menyelesaikan ini dengan metode hasOwnProperty:
tapi ini berlaku untuk iterasi atas objek apa pun dengan loop for-in.
Dua
Biasanya urutan item dalam array adalah penting, tetapi loop for-in tidak harus berulang dalam urutan yang benar, itu karena ia memperlakukan array sebagai objek, yang merupakan cara penerapannya dalam JS, dan tidak sebagai sebuah array. Ini sepertinya hal kecil, tetapi benar-benar dapat mengacaukan aplikasi dan sulit untuk di-debug.
sumber
Object.keys(a).forEach( function(item) { console.log(item) } )
beralih di atas array kunci properti sendiri, bukan yang diwarisi dari prototipe.array.forEach
dengan memasukkan kode tertentu ke dalam skrip Anda. Lihat Polyfill developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Karena ia menyebutkan melalui bidang objek, bukan indeks. Anda bisa mendapatkan nilai dengan indeks "panjang" dan saya ragu Anda menginginkannya.
sumber
Saya rasa saya tidak punya banyak hal untuk ditambahkan misalnya. Jawaban Triptych atau jawaban CMS tentang mengapa menggunakan
for...in
harus dihindari dalam beberapa kasus.Namun, saya ingin menambahkan bahwa di browser modern ada alternatif
for...in
yang dapat digunakan dalam kasus-kasus di manafor...in
tidak dapat digunakan. Alternatif itu adalahfor...of
:Catatan :
Sayangnya, tidak ada versi Internet Explorer yang mendukung
for...of
( Edge 12+ melakukannya), jadi Anda harus menunggu sedikit lebih lama hingga Anda dapat menggunakannya dalam kode produksi sisi klien Anda. Namun, aman untuk digunakan di kode JS sisi server Anda (jika Anda menggunakan Node.js ).sumber
for-of
, bukanfor-in
?Masalah dengan
for ... in ...
- dan ini hanya menjadi masalah ketika seorang programmer tidak benar-benar mengerti bahasa; itu bukan benar-benar bug atau apa pun - adalah bahwa itu berulang atas semua anggota objek (well, semua anggota enumerable , tapi itu detail untuk saat ini). Ketika Anda ingin beralih hanya pada properti yang diindeks dari array, satu-satunya cara dijamin untuk menjaga hal-hal konsisten secara semantik adalah dengan menggunakan indeks integer (yaitu,for (var i = 0; i < array.length; ++i)
loop gaya).Objek apa pun dapat memiliki sifat sewenang-wenang yang terkait dengannya. Tidak ada yang buruk tentang memuat properti tambahan ke instance array, khususnya. Kode yang ingin melihat hanya properti seperti array yang diindeks karena itu harus tetap berpegang pada indeks integer. Kode yang sepenuhnya menyadari apa yang perlu
for ... in
dan benar-benar perlu untuk melihat semua properti, baik maka itu juga ok.sumber
for in
, dibandingkan dengan reguler untuk loop, array tersebut akan diulang? (yang pada intinya, kinerja lambat, kan?)in
dalam satufor ... in
lingkaran hanya akanfor ... in
pada array; ada banyak alasan bagus untuk tidak melakukannya. Ini bukan masalah kinerja seperti masalah "pastikan tidak rusak".[{a:'hey',b:'hi'},{a:'hey',b:'hi'}]
:, tapi ya, saya mengerti.Juga, karena semantik, cara
for, in
memperlakukan array (yaitu sama dengan objek JavaScript lainnya) tidak selaras dengan bahasa populer lainnya.sumber
TL&DR: Menggunakan
for in
loop dalam array bukanlah kejahatan, pada kenyataannya justru sebaliknya.Saya pikir
for in
loop adalah permata dari JS jika digunakan dengan benar dalam array. Anda diharapkan memiliki kontrol penuh atas perangkat lunak Anda dan tahu apa yang Anda lakukan. Mari kita lihat kekurangan yang disebutkan dan buktikan satu per satu.Array.prototype
seharusnya telah dilakukan dengan menggunakanObject.defineProperty()
danenumerable
deskriptor mereka harus diatur kefalse
. Pustaka yang tidak melakukannya tidak boleh digunakan sama sekali.Object.setPrototypeOf
atau dengan Kelasextend
. Anda harus menggunakan lagiObject.defineProperty()
yang secara default mengaturwritable
,enumerable
danconfigurable
deskriptor propertifalse
. Mari kita lihat contoh sub-klasifikasi array di sini ...Jadi Anda tahu ..
for in
loop sekarang aman karena Anda peduli dengan kode Anda.for in
Loop lambat: Hell no. Ini sejauh ini metode iterasi tercepat jika Anda mengulang array jarang yang diperlukan dari waktu ke waktu. Ini adalah salah satu trik kinerja paling penting yang harus diketahui. Mari kita lihat sebuah contoh. Kami akan mengulangi array yang jarang.sumber
for in
loop mengungguli yang lain "jika" array jarang dan semakin banyak jika semakin besar ukurannya. Jadi saya telah mengatur ulang tes bangku untuk array jarangarr
,, dari ukuran ~ 10.000 dengan hanya 50 item yang dipilih secara[42,"test",{t:1},null, void 0]
acak di antara indeks acak. Anda akan segera melihat perbedaannya. - >> Periksa di sini << - .Selain masalah lain, sintaks "for..in" mungkin lebih lambat, karena indeksnya adalah string, bukan bilangan bulat.
sumber
var i in a
dan perkirakan indeksnya adalah bilangan bulat, maka melakukan sesuatu sepertia[i+offset] = <value>
akan meletakkan nilai di tempat yang sepenuhnya salah. ("1" + 1 == "11").Aspek penting adalah bahwa
for...in
hanya iterate atas properti yang terkandung dalam objek yang atribut enumerable properti mereka disetel ke true. Jadi, jika seseorang mencoba untuk mengulangi objek menggunakanfor...in
maka properti sewenang-wenang dapat dilewatkan jika atribut properti enumerable mereka salah. Sangat mungkin untuk mengubah atribut properti enumerable untuk objek Array normal sehingga elemen-elemen tertentu tidak disebutkan. Meskipun secara umum atribut properti cenderung berlaku untuk fungsi properti dalam suatu objek.Orang dapat memeriksa nilai atribut properti enumerable properti dengan:
Atau untuk memperoleh keempat atribut properti:
Ini adalah fitur yang tersedia di ECMAScript 5 - dalam versi sebelumnya tidak mungkin mengubah nilai atribut properti enumerable (selalu disetel ke true).
sumber
The
for
/in
bekerja dengan dua jenis variabel: hashtable (array asosiatif) dan array (non-asosiatif).JavaScript akan secara otomatis menentukan cara barang tersebut melewati item. Jadi, jika Anda tahu bahwa array Anda benar-benar non-asosiatif, Anda dapat menggunakan
for (var i=0; i<=arrayLen; i++)
, dan melewatkan iterasi deteksi otomatis.Tetapi menurut saya, lebih baik menggunakan
for
/in
, proses yang diperlukan untuk deteksi otomatis itu sangat kecil.Jawaban nyata untuk ini akan tergantung pada bagaimana parser / penterjemah kode JavaScript. Itu dapat berubah di antara browser.
Saya tidak dapat memikirkan tujuan lain untuk tidak menggunakan
for
/in
;sumber
Array
adalahObject
terlalufor ... in
bekerja dengan benda. Tidak ada yang namanya deteksi otomatis.Karena itu akan beralih pada properti yang dimiliki objek hingga rantai prototipe jika Anda tidak hati-hati.
Anda dapat menggunakan
for.. in
, pastikan untuk memeriksa setiap properti dengan hasOwnProperty .sumber
true
darihasOwnProperty()
cek.isNaN
cek pada setiap nama properti.isNaN
untuk memeriksa apakah suatu variabel adalah nilai khusus NaN atau tidak, itu tidak dapat digunakan untuk memeriksa 'hal-hal selain angka' (Anda dapat menggunakan reguler typeof untuk itu).Ini tidak selalu buruk (berdasarkan apa yang Anda lakukan), tetapi dalam kasus array, jika sesuatu telah ditambahkan
Array.prototype
, maka Anda akan mendapatkan hasil yang aneh. Di mana Anda mengharapkan loop ini berjalan tiga kali:Jika fungsi yang disebut
helpfulUtilityMethod
telah ditambahkan keArray
'sprototype
, maka loop Anda akan berakhir berjalan empat kali:key
akan0
,1
,2
, danhelpfulUtilityMethod
. Jika Anda hanya mengharapkan bilangan bulat, oops.sumber
Anda harus menggunakan
for(var x in y)
hanya pada daftar properti, bukan pada objek (seperti yang dijelaskan di atas).sumber
Menggunakan
for...in
loop untuk sebuah array tidak salah, walaupun saya bisa menebak mengapa seseorang memberi tahu Anda bahwa:1.) Sudah ada fungsi orde yang lebih tinggi, atau metode, yang memiliki tujuan untuk array, tetapi memiliki lebih banyak fungsi dan sintaks yang lebih ramping, yang disebut 'forEach':
Array.prototype.forEach(function(element, index, array) {} );
2.) Array selalu memiliki panjang, tetapi
for...in
danforEach
tidak menjalankan fungsi untuk nilai apa pun'undefined'
, hanya untuk indeks yang memiliki nilai yang ditentukan. Jadi jika Anda hanya menetapkan satu nilai, loop ini hanya akan mengeksekusi fungsi sekali, tetapi karena array dihitung, itu akan selalu memiliki panjang hingga indeks tertinggi yang memiliki nilai yang ditentukan, tetapi panjang itu bisa luput dari perhatian ketika menggunakan ini loop.3.) Standar untuk loop akan menjalankan fungsi sebanyak yang Anda tentukan dalam parameter, dan karena array diberi nomor, lebih masuk akal untuk menentukan berapa kali Anda ingin menjalankan suatu fungsi. Tidak seperti loop lainnya, loop for kemudian dapat menjalankan fungsi untuk setiap indeks dalam array, apakah nilainya didefinisikan atau tidak.
Intinya, Anda bisa menggunakan loop apa saja, tetapi Anda harus ingat persis cara kerjanya. Memahami kondisi di mana loop berbeda mengulangi, fungsi terpisah mereka, dan menyadari bahwa mereka akan lebih atau kurang sesuai untuk skenario yang berbeda.
Juga, mungkin dianggap sebagai praktik yang lebih baik untuk menggunakan
forEach
metode ini daripadafor...in
loop pada umumnya, karena lebih mudah untuk menulis dan memiliki lebih banyak fungsi, jadi Anda mungkin ingin membiasakan diri hanya menggunakan metode dan standar ini untuk, tetapi Anda panggilan.Lihat di bawah ini bahwa dua loop pertama hanya menjalankan pernyataan console.log sekali, sedangkan standar untuk loop mengeksekusi fungsi sebanyak yang ditentukan, dalam hal ini, array.length = 6.
sumber
Berikut adalah alasan mengapa ini (biasanya) merupakan praktik buruk:
for...in
loop mengulangi semua properti enumerable mereka sendiri dan properti enumerable prototipe mereka. Biasanya dalam iterasi array kita hanya ingin mengulangi array itu sendiri. Dan meskipun Anda sendiri mungkin tidak menambahkan apa pun ke array, pustaka atau kerangka kerja Anda mungkin menambahkan sesuatu.Contoh :
for...in
loop tidak menjamin urutan iterasi tertentu . Meskipun pesanan biasanya terlihat di sebagian besar browser modern hari ini, masih belum ada jaminan 100%.for...in
loop mengabaikanundefined
elemen array, yaitu elemen array yang belum ditetapkan.Contoh ::
sumber
untuk ... di berguna ketika bekerja pada objek dalam JavaScript, tetapi tidak untuk Array, tapi tetap saja kita tidak bisa mengatakan itu cara yang salah, tetapi tidak disarankan, lihat contoh di bawah ini menggunakan for ... in loop:
OK, mari kita lakukan dengan Array sekarang:
Seperti yang Anda lihat hasilnya sama ...
Tapi mari kita coba sesuatu, mari kita prototipe sesuatu ke Array ...
Sekarang kita membuat Array baru ();
Kalian lihat seseorang itu sendiri !!! ... Kita benar-benar mengulang-ulang objek Array baru dalam kasus ini!
Jadi itulah salah satu alasan mengapa kita perlu menggunakan untuk..dalam hati-hati, tapi itu tidak selalu terjadi ...
sumber
A for ... in loop selalu menyebutkan kunci. Kunci properti objek selalu berupa String, bahkan properti yang diindeks dari sebuah array:
sumber
Dari https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections
sumber
walaupun tidak secara khusus ditanggapi oleh pertanyaan ini, saya akan menambahkan bahwa ada alasan yang sangat baik untuk tidak pernah menggunakan ... dengan
NodeList
(karena orang akan mendapatkan dariquerySelectorAll
panggilan, karena tidak melihat elemen yang dikembalikan sama sekali, sebagai gantinya hanya mengulangi properti NodeList.dalam hal hasil tunggal, saya mendapat:
yang menjelaskan mengapa saya
for (node in nodes) node.href = newLink;
gagal.sumber