2009-11-04 47 views
23

xem xét vòng lặp như vậy:JavaScript biến ràng buộc và vòng lặp

for(var it = 0; it < 2; it++) 
{ 
    setTimeout(function() { 
     alert(it); 
    }, 1); 
} 

Đầu ra là:

=> 2 
=> 2 

Tôi muốn nó là: 0, 1. Tôi thấy hai cách để giải quyết nó:

Giải pháp # 1.

Điều này dựa trên thực tế là chúng tôi có thể chuyển dữ liệu đến setTimeout.

for(var it = 0; it < 2; it++) 
{ 
    setTimeout(function(data) { 
     alert(data); 
    }, 1, it); 
} 

Giải pháp # 2.

function foo(data) 
{ 
    setTimeout(function() { 
     alert(data); 
    }, 1); 
} 

for(var it = 0; it < 2; it++) 
{ 
    foo(it); 
} 

Có bất kỳ lựa chọn thay thế khác?

Trả lời

42

Không thực sự bất cứ điều gì nhiều hơn hai cách mà bạn đã đề xuất, nhưng đây là một

for(var it = 0; it < 2; it++) 
{ 
    (function() { 
     var m = it; 
     setTimeout(function() { 
      alert(m); 
     }, 1); 
    })(); 
} 

Về cơ bản, bạn cần phải nắm bắt được giá trị biến trong một đóng cửa. Phương thức này sử dụng một hàm ẩn danh được gọi ngay lập tức để nắm bắt giá trị biến bên ngoài it trong một biến cục bộ m.

Đây là số Working Demo để chơi cùng. thêm /chỉnh sửa vào URL để xem mã

+4

+1. Tuy nhiên, bạn có thể sửa đổi điều này bằng cách thay đổi chữ ký của phương thức thành: 'function (m) {/ * code * /}) (nó); ' – Alan

+0

+1, nhưng ai cũng có thể giải thích tại sao nó lại hoạt động ?! –

+1

@digorydoo Hàm được khai báo trong vòng lặp được bọc trong dấu ngoặc đơn, sau đó là một tập hợp các dấu ngoặc đơn hoạt động ngay lập tức để gọi hàm. Vì các biến được phạm vi đến hàm mà chúng được khai báo (hoặc phạm vi toàn cục nếu không được khai báo bên trong một hàm), giá trị của 'nó' trong mỗi lần lặp được gán cho biến' m' được phạm vi đến hàm được thi hành ngay. –

1

Tương tự như giải pháp trên nhưng tự cách gọi bên trong setTimeout chức năng

for(var it = 0; it < 2; it++) 
{ 
    setTimeout(function(cur) { 
     return function(){ 
      alert(cur); 
     }; 
    }(it), 1); 
} 
7

Với từ khóa cho phép bạn có thể khắc phục hoàn toàn sau:

for(let it = 0; it < 2; it++) 
{ 
    setTimeout(function() { 
     alert(it); 
    }, 1); 
} 
+0

nhưng không có từ khóa có tên là 'let' trong javascript, nó nằm trong kiểu chữ tôi nghĩ –

1

Tương tự như các giải pháp khác, nhưng theo ý kiến ​​của tôi sạch hơn:

for (var it = 0; it < 2; it++) { 
    // Capture the value of "it" for closure use 
    (function(it) { 
    setTimeout(function() { 
     alert(it); 
    }, 1); 
    // End variable captured code 
    })(it) 
} 

Điều này giữ cùng tên biến cho việc chụp, và thực hiện nó cho toàn bộ vòng lặp, tách nó khỏi logic của thiết lập thời gian chờ. Nếu bạn muốn thêm nhiều logic bên trong khối, bạn có thể làm điều đó một cách tầm thường.

Điều duy nhất tôi không thích về giải pháp là lặp lại "nó" ở cuối.

Các vấn đề liên quan