1

当我在 Google Chrome 中运行此示例代码时,预期的行为——在当前页面的占位符图像标签内加载图像——不会发生。我在调用 showPic() 时检查了 currPic 的值,它是“未定义的”。我知道如果我将 showPic 的参数从“anchors[i]”更改为“this”,那么它会起作用,但我试图理解为什么会这样。

function showPic(currPic) {
    var srcLoc = currPic.getAttribute("href");
    var placeHolder = document.getElementById("placeholder");
    placeHolder.setAttribute("src", srcLoc);
    var imgLabel = document.getElementById("imglabel");
    var currLinkTitle = currPic.getAttribute("title");
    imgLabel.firstChild.nodeValue = currLinkTitle;
}

function prepareGallery() {
    if(!(document.getElementsByTagName && document.getElementById)) return false;

    var imgGallery = document.getElementById("imagegallery");

    if(imgGallery) {
        var anchors = imgGallery.getElementsByTagName("a");
        var i;
        for(i = 0; i < anchors.length; i++) {
            anchors[i].onclick = function() {
                showPic(anchors[i]);
                return false;
        }  
        }
    }
}
4

3 回答 3

1

在匿名函数内部,anchors[i] 提供了运行时引用。在点击发生时,anchors[i]不再存在。虽然它在分配时存在,但在单击时它超出了范围(因为它只是一个数组引用)。但是, usingthis提供了对单击时始终可用的直接对象的可靠引用。

更简洁地说,anchors[i]是对数组中某个位置的引用(一旦 for 循环退出,它就会离开作用域)。this是对 dom 元素本身的引用。

于 2012-06-05T11:53:32.927 回答
0

因为这也行得通:showPic(document.getElementById(anchors[i].id));- 你现在“明白”了吗(双关语非常有意)?

于 2012-06-05T11:56:13.593 回答
0

没有看到关于闭包如何工作的明显声明,所以这是我的看法。

var i;
for(i = 0; i < anchors.length; i++) {
    anchors[i].onclick = function() {
        showPic(anchors[i]);
        return false;
    }
}

注意你是如何i在循环中引用变量的?在循环结束时,iequals的值anchors.length

因此,当您执行任何onclick函数时,对inow 的引用指向 ; 的最后一个索引之后的一个位置anchors。这就是为什么你看到currPic的是undefined

在其他答案中已经给出了这个问题的一个解决方案:用于this引用当前锚点并且不传递anchors[i]onclick函数。

由于您可能会遇到类似情况,我将通过关闭ilike 的值向您展示另一种解决方案:

var i;
for(i = 0; i < anchors.length; i++) {
    anchors[i].onclick = (function(i) {
        // inside this function, i is closed over and won't change anymore
        return function() {
            showPic(anchors[i]);
            return false;
        }
    }(i));
}
于 2012-06-06T03:39:01.657 回答