为什么FileReader.onload处理程序设置了自执行功能

时间:2014-07-09 18:15:46

标签: javascript filereader

遵循代码MDN for using files from web applications

function handleFiles(files) {
  for (var i = 0; i < files.length; i++) {
    var file = files[i];
    var imageType = /image.*/;

    if (!file.type.match(imageType)) {
      continue;
    }

    var img = document.createElement("img");
    img.classList.add("obj");
    img.file = file;
    preview.appendChild(img); // Assuming that "preview" is a the div output where the content will be displayed.

    var reader = new FileReader();
    reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
    reader.readAsDataURL(file);
  }
}

专注于这一行:

reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);

自执行功能背后的原因是什么?我知道 img 被传递给函数并在返回函数的方法中使用,但为什么它们不像这样引用它:

reader.onload = function(e) { img.src = e.target.result; };

1 个答案:

答案 0 :(得分:2)

for循环中没有特殊范围,因此在循环中声明变量会在每次迭代时覆盖变量,所以这个

for (var i = 0; i < 10; i++) {

    var img = document.createElement("img");

    setTimeout(function() {
        console.log(img);
    }, 100);

}

仅记录最后图片,十次。

setTimeout异步相同,reader.onload也是异步的,它稍后会执行回调,因为在循环内部错误地定义了img变量,需要创建一个闭包来创建一个新的范围来锁定img的值,它可以写得很好

(function(aImg) {

    reader.onload = function() {
        aImg.src = e.target.result;
    }

})(img);

某人刚刚决定变得有点聪明并且编写一个IIFE,在每次迭代中用一个返回函数的IIFE锁定img的值。

换句话说,如果他们只是在没有IIFE的情况下引用它,那么它们最终只能使用最后一个img,因为for循环将完成并在每次迭代时覆盖img变量,并且onload函数稍后执行,当循环完成并且img仅保存最后一个值时。