在循环内创建的函数中使用时,数组引用问题

时间:2012-05-09 14:44:54

标签: javascript

我知道,很好的称号; - )

无论如何,让我说我有以下代码(我这样做):

function GetArray(i) {
    if (i == 0) {
        return [1, 2, 3];
    }
    return [];
}

for (var i = 0; i < 3; i++) {
    var array = GetArray(i);

    var onClick = function() {
        alert(array.length);
    }

    var html = "<a>click me</a><br/>";
    var element = $(html);
    $("div").append(element);

    element.click(onClick);
}​

See working code here

单击3个链接,并注意每个值为0的警报。

我想要的是点击时第一个链接提醒3。

现在,在你们开始大喊为什么会发生这种情况之前,我得到的是onClick函数正在使用对数组的同一个实例的引用来清除,因此循环的每次迭代都“改变”了数组,而不是创建一个新的,这就是为什么实际上最后一个数组值用于所有点击事件。

所以问题是,我该怎样做才能完成工作?

我想过尝试“克隆”函数内部的那个不起作用的数组(我使用.slice(0))并且可能正确无效。另外,我猜它甚至可能只是用于所有3个事件的完全相同的功能。

2 个答案:

答案 0 :(得分:2)

每当发生这种情况时,它就是一个范围问题。每次通过数组时,都需要将数组锁定到onClick处理程序中。你可以通过自调用函数在它周围创建一个闭包来实现。

for (var i = 0; i < 3; i++) {
    var array = GetArray(i), onClick;

    // create a closure around onClick and array
    (function(array){
        onClick = function() {
            alert(array.length);
        }
    })(array);

    var html = "<a>click me</a><br/>";
    var element = $(html);
    $("div").append(element);

    element.click(onClick);
}​

注意这将警告3,0,0,因为第二次和第三次通过leep返回一个空数组。

答案 1 :(得分:0)

我同意hvgotcodes这是一个范围问题。这是避免在循环中创建函数的另一种方法,这在Javascript中总是有点冒险:

function GetArray(i) {
    if (i == 0) {
        return [1, 2, 3];
    }
    return [];
}

var onClickHelper = function(arrayLength) {
    return function () {
        alert(arrayLength);
    }
};

for (var i = 0; i < 3; i++) {
    var array = GetArray(i);    
    var onClick = onClickHelper(array.length);

    var html = "<a>click me</a><br/>";
    var element = $(html);
    $("div").append(element);

    element.click(onClick);
}