2012-06-01 15 views
5

Aşağıdaki kodda, ek parametreler alan image.onclick için bir olay işleyicisini tanımlamaya çalıştığımı göreceksiniz, bu parametrelerin içinde bulunduğunu açıklıyordum. döngü javascript tanımlanan kapsam bu şekilde değil ama değil. Temel olarak, tüm olay işleyicileri, değişkenlere id ve section_id verdiğim son değeri alıyorlar. Bu işleyicileri dinamik olarak oluşturmak istediğim bir durumun nasıl ele alınacağı konusunda bir fikrin var mı?Javascript - Dinamik olarak oluşturulmuş olay işleyicisine kapsam ve parametreleri aktarılıyor

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

} 

cevap

13

Oysa closures çözülür başka bir sorun!

dış fonksiyonu aynı anda çalıştırılır
image.onclick = function(id, section_id){ 
    return function(event) { 
     deleteImage(event,id,section_id); 
    } 
}(id, section_id); 

(ucunda bağımsız değişken ile parantez fark) ve bu tekrarda kendi sahası içerisinde olduğu gibi değişken bir kopyasını tutan iç fonksiyonu, döner döngünün

JavaScript, nesne olmayan değişkeni değer olarak geçirir, bu nedenle id ve section_id'u dış işleve geçirerek, bu işlevin bir kopyasını oluşturabilirsiniz. İçsel işlevi oluşturup döndürdüğünüzde, bu iç işlev, kapsamı oluşturulduğu anda kapsamdaki tüm değişkenleri kapsam dahilinde tutar (bu, id ve section_id yerel değişken kopyaları dahil olmak üzere, what a closure is'un tam kalbinde bulunur). İç işlevi, benzersiz kapsamı ile, bu öğe için olay işleyicisi haline gelir.

+0

Yardımlarınız için teşekkürler! – flips

+0

üzgünüm, nasıl yapıldığını bilmiyordum :) – flips

0

Bir kapatma kullanmanız gerekir. javascript 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) 

Kapsam bir dış fonksiyon döngü içinde belirli bir zamanda bu değişkenlerin değerini koruyacak kendisine geçirilen bağımsız değişkenlerle yürütmek sahip olmanın bir fonksiyonun küme parantezi içinde tanımlanabilir sen Onlara ihtiyacım var.

Bunlar olmadan, id ve section_id değerleri her zaman son yineleme sırasında sahip oldukları değere başvurur.

0

Bu, işlev kapsamı hakkında anlayış eksikliği nedeniyle ortaya çıkan klasik bir JavaScript sorundur. Bu hat üzerinde:

deleteImage(event,id,section_id); 

deleteImage geçirilen parametreler geri arama oluşturulduğu zaman onlar vardı değerlerini korumak gerektiğini hiçbir sebep yoktur. id ve section_id değişkenleri handlePicturesResult kapsamındadır; Onlar o mekanda var olan değişkenlerdir ve her birinin sadece bir kopyası vardır. Bu nedenle, geri arama çalıştırıldığında, bu belirli değişkenleri ve şu anda başvurdukları değerleri kullanır (döngünün son yinelemesinden). Çözüm, değişkenleri, değerlerini döngünün her yinelemesinde "kapatacak" bir kapsam elde etmektir. İşlevler, JS'de bu tür kapsamları sağlar. Sağlanan mükemmel çözümleri tekrarlamayacağım. Alternatif jQuery en each tekrarlamalar için kullanmak, ve yine bu sorun olmayacak:

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

}); 
  • pictures bir dizidir varsayar.
İlgili konular