“ var” หรือไม่“ var” ในลูป“ for-in” ของ JavaScript


101

วิธีที่ถูกต้องในการเขียนfor-inลูปใน JavaScript คืออะไร? เบราว์เซอร์ไม่ได้ส่งเรื่องร้องเรียนเกี่ยวกับสองวิธีที่ฉันแสดงที่นี่ ประการแรกมีวิธีการนี้ที่มีการxประกาศตัวแปรการวนซ้ำอย่างชัดเจน:

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

หรืออีกวิธีหนึ่งวิธีนี้ซึ่งอ่านเป็นธรรมชาติกว่า แต่ดูเหมือนจะไม่ถูกต้องสำหรับฉัน:

for (x in set) {
    ...
}

เพียงแค่มาในโพสต์นี้เมื่อแก้ไขทำไม webpack สร้างไฟล์กำก่อให้เกิดข้อผิดพลาดที่สำหรับวงที่varไม่ได้ใช้ในการประกาศการทำซ้ำโดย:i Uncaught ReferenceError: i is not definedดังนั้นฉันจะใช้ต่อจากนี้: / webpack ถือว่าตัวแปร "global" แปลก ๆ สำหรับข้อมูลเพิ่มเติมโปรดดู: stackoverflow.com/a/40416826
user1063287

คำตอบ:


104

ใช้varมันจะลดขอบเขตของตัวแปรมิฉะนั้นตัวแปรจะค้นหาการปิดที่ใกล้ที่สุดเพื่อค้นหาvarคำสั่ง หากไม่พบแสดงvarว่าเป็นโกลบอล (หากคุณอยู่ในโหมดเข้มงวดusing strictตัวแปรส่วนกลางจะทำให้เกิดข้อผิดพลาด) ซึ่งอาจนำไปสู่ปัญหาดังต่อไปนี้

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

หากคุณเขียนvar iสำหรับลูปการแจ้งเตือนจะแสดง2ขึ้น

JavaScript Scoping และ Hoisting


4
ไม่ตอบคำถามนี่เป็นเรื่องปกติสำหรับการวนซ้ำไม่ใช่สำหรับใน
IllidanS4 รองรับ Monica

ไม่ใช่เหตุผลที่ i == 5 เนื่องจากการยกมากกว่าการขาด var ใน for loop หรือ
Snekse

1
อีกแง่มุมหนึ่งของ importnat คือโหมดที่เข้มงวดห้ามไม่ให้สร้างคุณสมบัติ gobal โดยปริยายดังนั้นการใช้ลูป "for in" มาตรฐานโดยไม่มีคำสั่ง var จะล้มเหลวและส่งคืน ReferenceError
dkugappi

2
แต่มาจาก Java การใส่หัวvarด้านในforดูเหมือนว่าเป็นแบบ local ใน for loop ซึ่งไม่ใช่ ดังนั้นฉันชอบสไตล์ของ user422039 ด้านล่าง
njlarsson

2
จะเกิดอะไรขึ้นถ้าคุณมีมากกว่าหนึ่ง for-loop ในขอบเขตเดียว? คุณจะต้องใช้ดัชนีซ้ำ (ไม่มี var) หรือคุณจะต้องประกาศตัวแปรใหม่จำนวนมาก (j, k, l, m, ... ) ซึ่งคุณจะไม่ใช้อีก
armin

40

รุ่นแรก:

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

ประกาศตัวแปรท้องถิ่นที่เรียกว่าx. รุ่นที่สอง:

for (x in set) {
    ...
}

ไม่.

ถ้าxเป็นตัวแปรท้องถิ่นอยู่แล้ว (เช่นคุณมีvar x;หรือvar x = ...;อยู่ที่ไหนสักแห่งก่อนหน้านี้ในขอบเขตปัจจุบันของคุณ (เช่นฟังก์ชันปัจจุบัน)) ค่านั้นจะเทียบเท่า หากยังไม่ได้เป็นตัวแปรท้องถิ่นแล้วใช้สองโดยปริยายจะประกาศตัวแปรทั่วโลกx xพิจารณารหัสนี้:

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

คุณอาจคาดหวังนี้จะแจ้งเตือนhey, there, heli, hey, there, copter, แต่เนื่องจากxเป็นหนึ่งเดียวกันมันจะแจ้งเตือนhey, there, there, hey, ,there thereคุณไม่ต้องการสิ่งนั้น! ใช้var xในforลูปของคุณ

ปิดท้ายทั้งหมด: ถ้าforลูปอยู่ในขอบเขตส่วนกลาง (เช่นไม่อยู่ในฟังก์ชัน) ขอบเขตโลคัล (ขอบเขตxจะถูกประกาศในถ้าคุณใช้var x) จะเหมือนกับขอบเขตส่วนกลาง (ขอบเขตxถูกประกาศโดยปริยายใน หากคุณใช้xโดยไม่มี var) ดังนั้นทั้งสองเวอร์ชันจะเหมือนกัน


3
ในที่สุดคำตอบที่สมบูรณ์พร้อมคำอธิบายและตัวอย่างที่ดี และมันตอบคำถามจริงๆ
IllidanS4 รองรับ Monica

22

คุณควรประกาศตัวแปรท้องถิ่นที่มีvar, เสมอ

คุณไม่ควรใช้ลูป "for ... in" เว้นแต่คุณจะแน่ใจจริงๆว่านั่นคือสิ่งที่คุณต้องการทำ สำหรับการวนซ้ำผ่านอาร์เรย์จริง (ซึ่งเป็นเรื่องธรรมดา) คุณควรใช้ลูปที่มีดัชนีตัวเลขเสมอ:

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

การวนซ้ำผ่านอาร์เรย์ธรรมดาที่มี "for ... in" อาจส่งผลที่ไม่คาดคิดได้เนื่องจากลูปของคุณอาจรับแอตทริบิวต์ของอาร์เรย์นอกเหนือจากที่จัดทำดัชนีเป็นตัวเลข

แก้ไข - ที่นี่ในปี 2558 คุณสามารถใช้.forEach()เพื่อวนซ้ำผ่านอาร์เรย์ได้เช่นกัน:

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

.forEach()วิธีการอยู่บนต้นแบบอาร์เรย์จาก IE9 ไปข้างหน้า


12

อันที่จริงหากคุณไม่ชอบการประกาศภายในforหัวข้อคุณสามารถทำได้:

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

ดังที่ได้กล่าวไว้ในคำตอบอื่น ๆ สำหรับคำถามนี้การไม่ใช้varเลยก่อให้เกิดผลข้างเคียงที่ไม่จำเป็นเช่นการกำหนดทรัพย์สินส่วนกลาง


9

varใช้อย่างใดอย่างหนึ่งที่คุณประกาศตัวแปรห่วงด้วย ตัวแปรที่ประกาศโดยนัยมีขอบเขตที่แตกต่างกันซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ


9
for(var i = 0; ...)

เป็นรูปแบบที่เห็นได้ทั่วไป แต่แตกต่างจาก

for(int i; ...)

ใน C ++ ซึ่งตัวแปรไม่ได้กำหนดขอบเขตไว้ที่forบล็อก ในความเป็นจริงสิ่งที่varถูกยกขึ้นไปที่ด้านบนสุดของขอบเขตการปิดล้อม (ฟังก์ชัน) ดังนั้นโลคัลiจะพร้อมใช้งานได้อย่างมีประสิทธิภาพทั้งก่อนforลูป (หลังจากจุดเริ่มต้นของขอบเขต / ฟังก์ชันปัจจุบัน) และหลังจากนั้น

กล่าวอีกนัยหนึ่งการทำ:

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

เหมือนกับ:

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

ES6 มีletคีย์เวิร์ด (แทนvar) เพื่อ จำกัด ขอบเขตเฉพาะสำหรับบล็อก

แน่นอนว่าคุณควรใช้ตัวแปรท้องถิ่น (ตัวแปรที่ประกาศด้วยvarหรือletหรือconst(ใน ES6)) มากกว่าที่จะใช้โดยปริยาย

for(i=0; ...)หรือfor(i in ...)จะล้มเหลวหากคุณใช้"use strict";(เท่าที่ควร) และiไม่ได้รับการประกาศ


6

การใช้varเป็นวิธีที่สะอาดที่สุด แต่ทั้งสองได้ผลตามที่อธิบายไว้ที่นี่: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in

โดยพื้นฐานแล้วการใช้varคุณต้องแน่ใจว่าคุณได้สร้างตัวแปรใหม่ มิฉะนั้นคุณอาจใช้ตัวแปรที่กำหนดไว้ก่อนหน้านี้โดยไม่ได้ตั้งใจ


4

ฉันคิดว่า var นั้นดีสำหรับเหตุผลด้านประสิทธิภาพ

Javascript จะไม่มองผ่านขอบเขตส่วนกลางทั้งหมดเพื่อดูว่ามี x อยู่แล้วที่อื่นหรือไม่


3

จากมุมมองทั่วไปเวอร์ชันแรกจะเป็นดัชนีที่ต้องอยู่ภายในขอบเขตของลูปในขณะที่อีกตัวจะเป็นตัวแปรใด ๆ ในขอบเขตที่ตัวสร้างของลูปถูกเรียกใช้

หากคุณจะใช้ดัชนีของลูปภายในสำหรับลูปและสิ่งนี้ไม่จำเป็นสำหรับคนอื่นในบรรทัดถัดไปให้ประกาศตัวแปรด้วย "var" ดีกว่าดังนั้นคุณจะต้องแน่ใจว่า "x" เป็นดัชนีของลูปที่เริ่มต้นด้วย 0 ในขณะที่อีกตัวหนึ่งถ้าตัวแปร "x" อื่นพร้อมใช้งานในบริบทนี้สิ่งนี้จะถูกเขียนทับโดยดัชนีของลูปนั่นคือคุณจะมีข้อผิดพลาดทางตรรกะ -

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.