"Var" atau tidak ada "var" di loop "for-in" JavaScript?

99

Apa cara yang benar untuk menulis for-inloop di JavaScript? Browser tidak mengeluarkan keluhan tentang salah satu dari dua pendekatan yang saya tunjukkan di sini. Pertama, ada pendekatan ini di mana variabel iterasi xdideklarasikan secara eksplisit:

for (var x in set) {
    ...
}

Dan sebagai alternatif, pendekatan ini yang terbaca lebih alami tetapi tampaknya tidak benar bagi saya:

for (x in set) {
    ...
}
futlib
sumber
Hanya datang di posting ini ketika masalah mengapa Webpack dihasilkan file bundel menyebabkan kesalahan pada untuk loop di mana vartidak digunakan untuk menyatakan iterator i: Uncaught ReferenceError: i is not defined. Jadi saya akan menggunakannya mulai sekarang: / webpack memperlakukan variabel "global" dengan aneh, untuk lebih lanjut lihat: stackoverflow.com/a/40416826
user1063287

Jawaban:

103

Gunakan var, ini mengurangi ruang lingkup variabel jika variabel mencari penutupan terdekat mencari varpernyataan. Jika tidak dapat menemukan varmaka itu global (jika Anda dalam mode ketat using strict, variabel global membuat kesalahan). Hal ini dapat menyebabkan masalah seperti berikut ini.

function f (){
    for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

Jika Anda menulis var idi loop for, peringatan akan ditampilkan 2.

Scoping dan Hoisting JavaScript

Gabriel Llamas
sumber
4
Tidak menjawab pertanyaan, ini normal untuk loop, bukan untuk masuk
IllidanS4 ingin Monica kembali
Bukankah alasan i == 5 lebih karena mengangkat daripada kurangnya var di loop for?
Snekse
1
Aspek penting lainnya untuk ini adalah bahwa mode ketat melarang pembuatan implisit properti gobal, jadi menggunakan standar "for in" tanpa pernyataan var akan benar-benar gagal dan mengembalikan ReferenceError.
dkugappi
2
Tapi, berasal dari Java, meletakkan bagian vardalam forhead tampak seperti lokal di loop for, padahal sebenarnya tidak. Karenanya, saya lebih suka gaya user422039 di bawah ini.
njlarsson
2
Bagaimana jika Anda kebetulan memiliki lebih dari satu for-loop dalam satu lingkup? Anda harus menggunakan kembali indeks (tidak ada var), atau Anda harus mendeklarasikan banyak sekali variabel baru (j, k, l, m,…) yang tidak akan pernah Anda gunakan lagi.
armin
40

Versi pertama:

for (var x in set) {
    ...
}

mendeklarasikan variabel lokal yang dipanggil x. Versi kedua:

for (x in set) {
    ...
}

tidak.

Jika xsudah menjadi variabel lokal (yaitu Anda memiliki var x;atau di var x = ...;suatu tempat sebelumnya dalam lingkup Anda saat ini (yaitu fungsi saat ini)) maka mereka akan setara. Jika xbelum menjadi variabel lokal, maka menggunakan yang kedua akan secara implisit mendeklarasikan variabel global x. Pertimbangkan kode ini:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

Anda mungkin berharap ini peringatan hey, there, heli, hey, there, copter, tapi karena xsatu dan sama itu akan mengingatkan hey, there, there, hey, there, there. Anda tidak menginginkan itu! Gunakan var xdifor loop .

Untuk melengkapi semua ini: jika forloop berada dalam cakupan global (yaitu bukan dalam fungsi), maka cakupan lokal (cakupan xdideklarasikan jika Anda menggunakan var x) sama dengan cakupan global (cakupan xsecara implisit dideklarasikan dalam jika Anda menggunakan xtanpa var), maka kedua versi tersebut akan sama.

Claudiu
sumber
3
Akhirnya jawaban lengkap dengan penjelasan dan contoh yang bagus. Dan itu benar-benar menjawab pertanyaan itu.
IllidanS4 ingin Monica kembali
22

Anda benar-benar harus mendeklarasikan variabel lokal dengan var, always .

Anda juga tidak boleh menggunakan pengulangan "untuk ... dalam" kecuali Anda benar-benar yakin bahwa itu yang ingin Anda lakukan. Untuk iterasi melalui array nyata (yang cukup umum), Anda harus selalu menggunakan loop dengan indeks numerik:

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

Iterasi melalui array biasa dengan "for ... in" dapat menimbulkan konsekuensi yang tidak terduga, karena loop Anda mungkin mengambil atribut array selain yang diindeks secara numerik.

edit - di sini pada tahun 2015 juga boleh digunakan .forEach()untuk mengulang melalui array:

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

The .forEach()Metode hadir pada prototipe Array dari IE9 ke depan.

Runcing
sumber
12

Sebenarnya, jika Anda tidak menyukai deklarasi dalam forheading, Anda dapat melakukan:

var x;
for (x in set) {
    ...
}

Seperti yang disebutkan dalam jawaban lain untuk pertanyaan ini, tidak menggunakan varsama sekali menghasilkan efek samping yang tidak perlu seperti menetapkan properti global.

pengguna422039
sumber
9

Gunakan salah satu tempat Anda mendeklarasikan variabel loop dengan var. Variabel yang dideklarasikan secara implisit memiliki cakupan berbeda yang mungkin bukan yang Anda inginkan.

Joel Coehoorn
sumber
9
for(var i = 0; ...)

adalah pola yang umum terlihat tetapi berbeda dari

for(int i; ...)

di C ++ karena variabel tidak dicakup ke forblok. Faktanya, yang vardiangkat ke atas lingkup penutup (fungsi) sehingga lokal iakan tersedia secara efektif baik sebelum forloop (setelah awal ruang lingkup / fungsi saat ini) dan setelahnya.

Dengan kata lain, melakukan:

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

sama dengan:

(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6 memiliki letkata kunci (bukan var) untuk membatasi cakupan ke blok for.

Tentu saja, Anda HARUS menggunakan variabel lokal (yang dideklarasikan dengan varatau letatau const(dalam ES6)) daripada variabel global implisit.

for(i=0; ...)atau for(i in ...)akan gagal jika Anda menggunakan "use strict";(sebagaimana mestinya) dan itidak dideklarasikan.

PSkocik
sumber
4

Saya pikir var bagus untuk alasan kinerja.

Javascript tidak akan melihat seluruh cakupan global untuk melihat apakah x sudah ada di tempat lain.

neebz
sumber
3

Dari sudut pandang umum, versi pertama adalah untuk indeks yang harus hidup dalam lingkup loop, sedangkan yang lain akan menjadi variabel dalam lingkup di mana konstruktor loop dipanggil.

Jika Anda akan menggunakan indeks loop di dalam for loop dan ini tidak akan diperlukan oleh orang lain di baris berikutnya, lebih baik deklarasikan variabel dengan "var" sehingga Anda akan yakin "x" untuk indeks loop yang diinisialisasi dengan 0, sedangkan yang lainnya, jika variabel "x" lain tersedia dalam konteks ini, ini akan ditimpa oleh indeks loop - Anda akan memiliki beberapa kesalahan logika -.

Matías Fidemraizer
sumber