检测到的循环计数器变量值错误

时间:2015-12-10 13:40:36

标签: javascript jquery

我的测试代码:

var imageUploadPreview = function (e) {
  var input = document.getElementById("file"),
      files = e.target.files;

    for (var i = 0; i < files.length; i++) {
        if (input.files) {
            var file = files[i],
                reader = new FileReader();

            reader.onload = function (e) {
                (function (i) {
                    var img = $('<img>').prop('id', 'img_' + i)
                     .prop('src', e.target.result).css({'width':'60px', 'height':'60px'});

                    var div = $('<div>').append(img).append(img.prop('id'))
                    $('body').append(div);
                })(i)
            }
            reader.readAsDataURL(file);
        }
    }
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<input type="file" id="file" onchange="imageUploadPreview(event)" multiple />

它的工作原理除外:所有图像ID都是 img_ + files.length

你能解释一下为什么吗?循环会发生什么?

2 个答案:

答案 0 :(得分:3)

你几乎用iife执行i,你需要把它移到onload之外。问题是onload是异步调用的,所以当它运行时循环就完成了。这就是i是每个文件的最后一个索引的原因。你需要在onload运行之前执行iife。

        reader.onload = function (e) {
            (function (i) {
                var img = $('<img>').prop('id', 'img_' + i)
                 .prop('src', e.target.result).css({'width':'60px', 'height':'60px'});

                var div = $('<div>').append(img).append(img.prop('id'))
                $('body').append(div);
            })(i)
        }

(function (i) {
    reader.onload = function (e) {
        var img = $('<img>').prop('id', 'img_' + i)
            .prop('src', e.target.result).css({
                'width': '60px',
                'height': '60px'
            });

        var div = $('<div>').append(img).append(img.prop('id'))
        $('body').append(div);
    }
})(i);

答案 1 :(得分:2)

您对reader.readAsDataURL(file);的呼叫是异步的。

这意味着reader.onload函数不会同步执行循环。因此,当执行加载函数时,循环变量的值是不可预测的。

在将循环变量传递给它之后,将reader.onload与另一个函数封装在一起。

for(i) {
   function(loopVar) {
      reader.onload = function () {
          //use loopVar here
      }(i)
}

这里注册循环变量i作为封装函数的参数。无论何时执行回调函数,该值在传递时仍将保留。