为什么我的匿名函数在此示例中没有当前对象的上下文?

时间:2012-06-05 11:49:34

标签: javascript

当我在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;
        }  
        }
    }
}

3 个答案:

答案 0 :(得分:1)

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

更简洁地说,anchors[i]是对数组中位置的引用(一旦for循环退出就会留下范围)。 this是对dom元素本身的引用。

答案 1 :(得分:0)

因为这也有效:showPic(document.getElementById(anchors[i].id)); - 你现在“得到”它(非常有意思)?

答案 2 :(得分:0)

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

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

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

因此,当执行onclick函数的任何时,对i的引用现在指向一个位置超过anchors的最后一个索引;这就是为什么您看到currPicundefined

其他答案中给出了此问题的一种解决方案:使用this引用当前锚点,不要将anchors[i]传递给onclick函数。

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

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