2012-06-01 26 views
5

Trong mã bên dưới, bạn sẽ thấy rằng tôi đang cố gắng xác định trình xử lý sự kiện cho image.onclick, có tham số bổ sung, tôi đã khai báo các tham số đó trong vòng lặp hy vọng javascript được xác định phạm vi theo cách này nhưng nó không. Về cơ bản tất cả các trình xử lý sự kiện ở đây đang nhận được giá trị cuối cùng mà tôi cung cấp cho các biến id và section_id. Bất kỳ ý tưởng về cách xử lý một tình huống mà tôi muốn được tạo ra các xử lý động?Javascript - Vấn đề với phạm vi và các tham số truyền cho trình xử lý sự kiện được tạo động

function handlePicturesResult(){ 
    if (req.readyState == 4) { // Complete 
     if (req.status == 200) { // OK response 

      var el = document.getElementById('pictureHolder'); 
      while(el.hasChildNodes()){ 
       el.removeChild(el.lastChild); 
      } 

      var tempObject = JSON.parse(req.responseText); 
      var pictures = tempObject.images; 
      var i=0; 

      while(i<pictures.length){ 

       var picIndex = i; 

       var image= new Image(120,80); 
       image.src = 'images/' + pictures[i].url; 
       image.width = 120; 
       image.height = 80; 
       var id = pictures[picIndex].id; 
       var section_id = pictures[picIndex].sectionId; 
       image.onclick = function(event){ 
        deleteImage(event,id,section_id); 
       } 


       var txtNode = document.createTextNode(pictures[picIndex.valueOf()].id); 
       el.appendChild(image); 
       el.appendChild(txtNode); 
       i++; 
      } 
     } else { 
     alert("Problem: " + req.statusText); 
     } 
    } 

} 

Trả lời

13

Một vấn đề khác được giải quyết bởi closures!

image.onclick = function(id, section_id){ 
    return function(event) { 
     deleteImage(event,id,section_id); 
    } 
}(id, section_id); 

Chức năng bên ngoài đang chạy cùng một lúc (chú ý dấu ngoặc đơn với các đối số ở cuối), và nó trả về chức năng bên trong, mà giữ trong phạm vi của nó một bản sao của các biến như họ đang ở lặp mà của vòng lặp.

JavaScript chuyển biến không đối tượng theo giá trị, do đó, bằng cách chuyển idsection_id sang hàm ngoài, bạn tạo bản sao của chúng bên trong hàm đó. Khi bạn tạo và trả về hàm bên trong, hàm bên trong đó giữ trong phạm vi tất cả các biến nằm trong phạm vi thời điểm tạo của nó (đây là trung tâm của what a closure is), bao gồm các bản sao biến cục bộ idsection_id. Hàm bên trong, với phạm vi duy nhất của nó, trở thành trình xử lý sự kiện cho phần tử đó.

+0

cảm ơn vì sự giúp đỡ của bạn! – flips

+0

xin lỗi không biết làm thế nào để tôi đã làm bây giờ :) – flips

0

Bạn cần sử dụng đóng. https://developer.mozilla.org/en/JavaScript/Guide/Closures

image.onclick = function(id, s_id){ 
    return function(event){ 
    deleteImage(event, id, s_id); 
    } 
}(id, section_id) 

Scope trong javascript có thể được định nghĩa trong dấu ngoặc nhọn của một hàm, mà lý do tại sao có một chức năng bên ngoài thực hiện với các đối số được truyền cho nó mà vẫn duy trì giá trị của các biến vào thời điểm cụ thể trong vòng lặp bạn cần họ.

Không có chúng, giá trị của id và section_id sẽ luôn tham chiếu giá trị mà chúng có trong lần lặp cuối cùng.

0

Đây là vấn đề JavaScript cổ điển bắt nguồn từ sự thiếu hiểu biết về phạm vi chức năng. On line này:

deleteImage(event,id,section_id); 

không có lý do rằng các tham số truyền cho deleteImage nên giữ lại các giá trị mà họ đã lúc khi gọi lại được tạo ra. Các biến số idsection_id được giới hạn trong phạm vi handlePicturesResult; chúng là các biến tồn tại trong không gian đó và chỉ có một bản sao của mỗi biến. Do đó, khi gọi lại chạy, nó sẽ sử dụng các biến cụ thể đó và các giá trị mà chúng hiện đang đề cập đến (từ lần lặp cuối cùng của vòng lặp).

Giải pháp là đưa các biến vào phạm vi "tiết kiệm" giá trị của chúng mỗi lần lặp của vòng lặp. Các hàm chỉ cung cấp các phạm vi như vậy trong JS. Tôi sẽ không lặp lại các giải pháp tuyệt vời đã được cung cấp. Một cách khác là sử dụng jQuery each cho lần lặp lại, và bạn sẽ không có vấn đề này một lần nữa:

$.each(pictures, function(i, picture) { 

    var image= new Image(120,80); 
    var id = pictures.id; 
    var section_id = picture.sectionId; 
    var txtNode = document.createTextNode(id); 

    image.width = 120; 
    image.height = 80; 
    image.src = 'images/' + picture.url; 

    image.onclick = function(event){ 
     deleteImage(event, id, section_id); 
    } 

    el.appendChild(image); 
    el.appendChild(txtNode); 

}); 
  • Giả pictures là một mảng.
Các vấn đề liên quan