2013-07-16 31 views
7

Hãy xem jsfiddle: http://jsfiddle.net/LsNCa/2/JavaScript- biến Phạm vi và xử lý sự kiện

function MyFunc() { 

    for (var i = 0; i < 2; i++) { // i= 0, 1 
     var myDiv = $('<div>'); 

     myDiv.click(function(e) { 
      alert(i); // both the two divs alert "2", not 0 and 1 as I expected 
     }); 
     $('body').append(myDiv); 
    } 
} 

var myFunc = new MyFunc(); 

Tôi muốn các divs để cảnh báo "0" và "1" tương ứng khi tôi nhấp vào chúng. Nhưng cả hai đều cảnh báo "2".

Khi tôi nhấp vào các div và sự kiện được kích hoạt, trình xử lý tìm giá trị của biến i ở đâu và ở đâu?

Tôi biết rằng việc thêm đóng cửa đạt được mục tiêu của mình. Nhưng tại sao?

+0

có thể trùng lặp với [Vấn đề về vòng lặp Javascript khét tiếng?] (Http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem) – elclanrs

Trả lời

7
function MyFunc() { 

    for (var i = 0; i < 2; i++) { // i= 0, 1 
     (function(j) { 
      var myDiv = $('<div>'); 

      myDiv.click(function(e) { 
       alert(j); 
      }); 
      $('body').append(myDiv); 
     })(i); 
    } 
} 

var myFunc = new MyFunc(); 

Mã trên là cách bạn làm cho nó hoạt động chính xác. Không đóng cửa, bạn luôn là giá trị cuối cùng của i. Những gì chúng tôi làm là để đăng i vào đóng cửa và để cho thời gian chạy "nhớ" giá trị của thời điểm đó rất.

+0

Đây có phải là cách làm tiêu chuẩn không? Nếu thân vòng lặp khá dài, chúng ta vẫn quấn nó bên trong một hàm ẩn danh? – Boyang

+0

Đây là thành ngữ thông thường. Nhưng bạn có thể sử dụng phong cách của Zenwolf nếu bạn thích các chức năng dài hơn. – Barmar

+0

Như tôi có thể thấy mọi người thường viết theo cách này. cố gắng không làm điều này trong một vòng lặp lớn. Tôi có nghĩa là thích (var i = 0; i <1000; i ++). – yaoxing

2

Bạn cần đóng vì tất cả các hàm xử lý sự kiện của bạn đang tham chiếu cùng một biến i. Vòng lặp for cập nhật điều này và khi vòng lặp được thực hiện biến chứa 2. Sau đó, khi ai đó nhấp vào một trong các DIV, nó sẽ truy cập biến đó.

Để giải quyết điều này, mỗi trình xử lý sự kiện cần phải đóng cửa với biến riêng i có chứa ảnh chụp nhanh của giá trị tại thời điểm đóng cửa được tạo.

+0

Bạn có thể viết một số mã không? Cho mục đích minh họa. :) – Boyang

+0

Bạn nói rằng bạn biết đúng cách để viết nó, bạn chỉ muốn có một giải thích về lý do tại sao đó là cần thiết. Tôi không chắc mã nào tôi có thể viết sẽ minh họa câu trả lời - mã của bạn làm điều đó tốt. – Barmar

1

tôi đề nghị bạn đọc this article

Javascript Tời tờ khai. Điều này có nghĩa là cả hai câu lệnh var và khai báo hàm sẽ được di chuyển lên đầu phạm vi kèm theo của chúng.

Như @Barmar đã nói trong câu trả lời của mình ở trên, biến số i đang được tham chiếu bởi cả trình xử lý sự kiện.

Bạn nên tránh khai báo hàm trong vòng lặp. Dưới đây là một số mã làm những gì bạn cần.

Tôi cho rằng bạn đang sử dụng jQuery.

function MyFunc() { 

    for (var i = 0; i < 2; i++) { // i= 0, 1 
     var myDiv = $('<div>'); 

     $('body').append(myDiv); 
    } 
    $('div').on('click', function() { 
     alert($(this).index()); 
    }); 
} 

var myFunc = new MyFunc(); 
0

Cuộc gọi "alert()" xảy ra sau khi vòng lặp hoàn thành, có nghĩa là giá trị "i" sẽ là giá trị cuối cùng cho bất kỳ điều gì sau đó. Để nắm bắt các giá trị cá nhân của "i", bạn phải tạo một kết thúc cho mỗi giá trị bằng cách tạo ra một chức năng mới:

function MyFunc() { 

    function alertFn(val) { 
     return function() { 
      alert(val); 
     }; 
    } 

    for (var i = 0; i < 2; i++) { 
     var myDiv = $('<div>'); 
     myDiv.click(alertFn(i)); 
     $('body').append(myDiv); 
    } 
} 

var myFunc = new MyFunc(); 

Việc đóng cửa nắm bắt được giá trị của "i" vào thời điểm đó nó đã được thông qua vào chức năng , cho phép alert() hiển thị giá trị bạn mong đợi.

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