繁体   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