“Var” hay không có “var” trong vòng lặp “for-in” của JavaScript?


99

Cách chính xác để viết một for-invòng lặp trong JavaScript là gì? Trình duyệt không đưa ra khiếu nại về một trong hai cách tiếp cận mà tôi trình bày ở đây. Đầu tiên, có cách tiếp cận này trong đó biến lặp xđược khai báo rõ ràng:

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

Và cách khác, cách tiếp cận này đọc tự nhiên hơn nhưng dường như không đúng với tôi:

for (x in set) {
    ...
}

Chỉ cần đi qua bài này khi xử lý sự cố tại sao một webpack tạo bó tập tin đã gây ra lỗi ở một vòng lặp for nơi varkhông được sử dụng để khai báo các iterator i: Uncaught ReferenceError: i is not defined. Vì vậy, tôi sẽ sử dụng nó từ bây giờ: / webpack xử lý biến "toàn cầu" thật là thú vị, cho thấy hơn: stackoverflow.com/a/40416826
user1063287

Câu trả lời:


103

Sử dụng var, nó làm giảm phạm vi của biến, nếu không, biến sẽ tìm kiếm sự đóng gần nhất để tìm kiếm một varcâu lệnh. Nếu nó không thể tìm thấy varthì nó là toàn cục (nếu bạn đang ở chế độ nghiêm ngặt using strict, các biến toàn cục sẽ gây ra lỗi). Điều này có thể dẫn đến các vấn đề như sau.

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

Nếu bạn viết var itrong vòng lặp for, cảnh báo sẽ hiển thị 2.

JavaScript Scoping và Hosts


4
Không trả lời câu hỏi, này là dành cho bình thường đối với vòng lặp, không cho tại.
IllidanS4 muốn Monica trở lại

Không phải lý do tôi == 5 do lưu trữ nhiều hơn là do thiếu var trong vòng lặp for?
Snekse

1
Một khía cạnh khác của importnat là chế độ nghiêm ngặt cấm tạo ra các thuộc tính gobal ngầm, vì vậy việc sử dụng vòng lặp "for in" tiêu chuẩn với câu lệnh var sẽ thực sự bị lỗi và trả về một ReferenceError.
dkugappi

2
Tuy nhiên, đến từ Java, việc đưa phần đầu varvào bên trong có forvẻ như nó cục bộ trong vòng lặp for, nhưng không phải vậy. Do đó, tôi thích phong cách của user422039 bên dưới hơn.
njlarsson

2
Điều gì sẽ xảy ra nếu bạn có nhiều vòng lặp for trong một phạm vi? Bạn sẽ phải sử dụng lại chỉ mục (không có var), hoặc bạn sẽ phải khai báo rất nhiều biến mới (j, k, l, m,…) mà bạn sẽ không bao giờ sử dụng lại.
armin

40

Phiên bản đầu tiên:

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

khai báo một biến cục bộ được gọi x. Phiên bản thứ hai:

for (x in set) {
    ...
}

không làm.

Nếu xđã là một biến cục bộ (tức là bạn có một var x;hoặc var x = ...;một nơi nào đó trước đó trong phạm vi hiện tại của bạn (tức là hàm hiện tại)) thì chúng sẽ tương đương. Nếu xchưa phải là biến cục bộ, thì việc sử dụng biến thứ hai sẽ ngầm khai báo một biến toàn cục x. Hãy xem xét mã này:

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

bạn có thể mong đợi điều này để cảnh báo hey, there, heli, hey, there, copter, nhưng kể từ khi xlà một và giống nhau nó sẽ cảnh báo hey, there,there , hey, there, there. Bạn không muốn điều đó! Sử dụng var xtrong các forvòng lặp của bạn .

Trên hết: nếu forvòng lặp nằm trong phạm vi toàn cục (tức là không nằm trong một hàm), thì phạm vi cục bộ (phạm vi xđược khai báo trong nếu bạn sử dụng var x) giống với phạm vi toàn cục (phạm vi xđược khai báo ngầm trong nếu bạn sử dụng xmà không có var), vì vậy hai phiên bản sẽ giống hệt nhau.


3
Cuối cùng là một câu trả lời đầy đủ với lời giải thích và ví dụ tốt đẹp. Và nó thực sự trả lời câu hỏi.
IllidanS4 muốn Monica trở lại

22

Bạn thực sự nên khai báo các biến cục bộ với var, luôn luôn .

Bạn cũng không nên sử dụng vòng lặp "for ... in" trừ khi bạn hoàn toàn chắc chắn rằng đó là những gì bạn muốn làm. Để lặp qua các mảng thực (điều này khá phổ biến), bạn nên luôn sử dụng một vòng lặp có chỉ mục số:

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

Việc lặp đi lặp lại một mảng thuần túy với "for ... in" có thể gây ra những hậu quả không mong muốn, vì vòng lặp của bạn có thể nhận các thuộc tính của mảng bên cạnh các thuộc tính được lập chỉ mục số.

chỉnh sửa - ở đây vào năm 2015, bạn cũng có thể sử dụng .forEach()để lặp qua một mảng:

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

Các .forEach()phương pháp được trình bày trên nguyên mẫu Mảng từ IE9 về phía trước.


12

Trên thực tế, nếu bạn không thích khai báo trong fortiêu đề, bạn có thể làm:

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

Như đã đề cập trong các câu trả lời khác cho câu hỏi này, việc hoàn toàn không sử dụng sẽ vartạo ra các tác dụng phụ không cần thiết như gán thuộc tính toàn cục.


9

Sử dụng cái mà bạn khai báo biến vòng lặp với var. Các biến được khai báo ngầm có một phạm vi khác có thể không phải như bạn dự định.


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

là một mẫu thường thấy nhưng nó khác với

for(int i; ...)

trong C ++, trong đó biến không được xác định phạm vi cho forkhối. Trên thực tế, varnó được nâng lên trên cùng của phạm vi bao quanh (chức năng), do đó, một cục bộ isẽ có sẵn một cách hiệu quả cả trước forvòng lặp (sau khi bắt đầu phạm vi / chức năng hiện tại) và sau nó.

Nói cách khác, làm:

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

giống như:

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

ES6 có lettừ khóa (thay vì var) để giới hạn phạm vi đối với khối for.

Tất nhiên, bạn NÊN sử dụng các biến cục bộ (những biến được khai báo bằng varhoặc lethoặc const(trong ES6)) hơn là toàn cầu ngầm định.

for(i=0; ...)hoặc for(i in ...)sẽ không thành công nếu bạn sử dụng "use strict";(như bạn nên làm) và ikhông được khai báo.



4

Tôi nghĩ rằng var là tốt vì lý do hiệu suất.

Javascript sẽ không xem xét toàn bộ phạm vi toàn cục để xem x đã tồn tại ở một nơi nào khác hay chưa.


3

Từ quan điểm chung, phiên bản đầu tiên sẽ dành cho một chỉ mục phải nằm trong phạm vi của vòng lặp, trong khi phiên bản còn lại sẽ là bất kỳ biến nào trong phạm vi mà hàm tạo của vòng lặp được gọi.

Nếu bạn định sử dụng chỉ mục của vòng lặp bên trong vòng lặp for và điều này sẽ không được những người khác yêu cầu trong các dòng tiếp theo, tốt hơn hãy khai báo biến bằng "var" để bạn chắc chắn "x" là chỉ mục của vòng lặp được khởi tạo bằng 0, trong khi biến còn lại, nếu biến "x" khác có sẵn trong ngữ cảnh này, thì biến này sẽ bị ghi đè bởi chỉ mục của vòng lặp - đó là bạn sẽ có một số lỗi logic -.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.