Javascript变量问题

时间:2011-07-10 10:11:01

标签: javascript

我在Javascript中有一个字符串数组,我需要用它来通过AJAX在我的页面中加载图像。加载每个图像后,我需要执行一些额外的任务,例如发送实际删除图像的HTTP请求。

这是我到目前为止所做的。

for (x in images) {
    var img = new Image();
    $(img)
        .load(function(){
            $('#image_'+images[x]).html(''); //remove loading gif
            $('#image_'+images[x]).append(this);
            $.post('/images/destroy_image',{id:images[x]});
        })
        .attr('src', '/images/get_image?id='+images[x]);
}

如果images数组中只有1个字符串,则此代码可以正常工作。

如果有多于1个,当图像完成加载并运行其load函数时,其images[x]函数中对load的任何引用现在指向最后一个字符串。 images数组,当我需要它时,它是循环运行时的值。

例如

images{'12','100'}

当第一张图片完成加载时,其load函数中的第一行将作为

运行
$('#image_100').html('');

什么时候应该

$('#image_12').html('');

我该怎么做?

4 个答案:

答案 0 :(得分:3)

典型的函数在循环问题。您必须通过引入新范围(通过函数,没有块范围)来“捕获”x的当前值。你可以这样做:

function loadImage(image) {
    $('<img />')
        .load(function(){
            $('#image_'+image).html(''); //remove loading gif
            $('#image_'+image).append(this);
            $.post('/images/destroy_image',{id:image]});
        })
        .attr('src', '/images/get_image?id='+image);
}

for (var i = 0, l = images.length; i < l; i++) { // it seems `images` is an array 
    loadImage(images[i]);
}

Don't use a for...in loop to iterate over arrays.

答案 1 :(得分:2)

jquery的each()函数关闭数组中的每个值,因此您最终不会引用最后一个值:

$.each(images, function(i,v) {
    var img = new Image();
    $(img)
        .load(function(){
            $('#image_'+v).html(''); //remove loading gif
            $('#image_'+v).append(this);
            $.post('/images/destroy_image',{id:v});
        })
        .attr('src', '/images/get_image?id='+v);
});

答案 2 :(得分:0)

尝试使用传统的for循环,这样你就可以拥有一个计数器。我认为你的foreach循环中的“x”是实际的对象,而不是索引值,但你可以像其他地方的索引一样使用它。这样可以解决吗?

答案 3 :(得分:0)

由于在经常解释闭包的方式和它们在大多数语言中实际工作的方式之间存在一些语义差异,因此您遇到了这个问题。如果没有涉及该主题,您可能会有更好的运气:

for (var index = 0; index < images.length; index++) {
    var img = new Image();
    $(img)
        .load(load(images[index]))
        .attr('src', '/images/get_image?id='+image);
}

function load(image) {
    return function() {
        $('#image_'+image).html(''); //remove loading gif
        $('#image_'+image).append(this);
        $.post('/images/destroy_image',{id:image});
    };
} 

如果您想进入上一个示例失败的原因,那么闭包通常被解释为创建当前词法范围中存在的状态的快照。这是一个有点误导性的类比,因为与不可变的真实快照不同,闭包内部的状态继续存在,并且可以通过闭包之外发生的事情进行修改。

例如,当您执行以下操作时:

for (x in myArray) {
    setTimeout(function() {
        alert(myArray[x]);
    }, 2000);
}

...只有x引用的单个变量实例,并且闭包正在捕获引用x,而不是当前的快照值x。因此,当后续迭代修改此范围中存在的x的单个实例的值时,更改将显示在使用x引用创建的每个闭包中。

当你这样做时它会起作用:

for (x in myArray) {
    var item = myArray[x];
    setTimeout(makeClosure(item), 2000);
}

function makeClosure(value) {
    return function() {
        alert(value);
    };
}

...因为在每次迭代时创建了一个不同的变量引用(通过调用makeClosure()),并且一旦创建,该值就永远不会被修改。创建的每个闭包都带有对最近定义的值的引用,因此在执行时似乎“记住”正确的值。