簡體   English   中英

Javascript - 范圍問題和將參數傳遞給動態創建的事件處理程序

[英]Javascript - Issue with scope and passing parameters to dynamically created event handler

在下面的代碼中,您將看到我正在嘗試為image.onclick定義一個事件處理程序,它需要額外的參數,我在while循環中聲明了這些參數,希望javascript定義范圍這樣,但事實並非如此。 基本上這里的所有事件處理程序都獲得了我給變量id和section_id的最后一個值。 關於如何處理我想要動態生成這些處理程序的情況的任何想法?

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

}

關閉解決了另一個問題!

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

外部函數立即運行(注意末尾帶有參數的括號),並返回內部函數,該函數在其范圍內保留變量副本,就像它們在循環的迭代中一樣。

JavaScript按值傳遞非對象變量,因此通過將idsection_id傳遞給外部函數,可以在該函數內創建它們的副本。 當您創建並返回內部函數時,該內部函數會在其創建時保留范圍內的所有變量(這是閉包的核心),包括idsection_id的局部變量副本。 內部函數及其唯一范圍成為該元素的事件處理程序。

你需要使用一個閉包。 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)

javascript中的范圍可以在函數的花括號中定義,這就是為什么外部函數執行時傳遞給它的參數將在你需要的循環中的特定時間保留這些變量的值。

沒有它們,id和section_id的值將始終引用它們在最后一次迭代時所具有的值。

這是一個典型的JavaScript問題,源於對功能范圍缺乏了解。 在這一行:

deleteImage(event,id,section_id);

沒有理由認為傳遞給參數deleteImage應保留他們在當時創建回調時的值。 變量idsection_id綁定到handlePicturesResult的范圍; 它們是該空間中存在的變量,每個變量只有一個副本。 因此,當回調運行時,它將使用那些特定變量及它們當前引用的值(來自循環的最后一次迭代)。

解決方案是將變量放入一個范圍,在每次循環迭代時“保存”它們的值。 函數在JS中提供了唯一的這樣的范圍。 我不會重復已經提供的優秀解決方案。 另一種方法是使用jQuery的each對迭代,你將不會再有這樣的問題:

$.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是一個數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM