按照代码 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; };
最佳答案
for
循环中没有特殊作用域,因此在循环内声明变量会在每次迭代时覆盖该变量,所以这
for (var i = 0; i < 10; i++) {
var img = document.createElement("img");
setTimeout(function() {
console.log(img);
}, 100);
}
将仅记录最后 图像,十次。
同理setTimeout
是async的,reader.onload
也是async的,它在后面的时间执行回调,所以因为里面img变量定义错误循环需要一个闭包来创建一个新的作用域来锁定 img
的值,它也可以写成
(function(aImg) {
reader.onload = function() {
aImg.src = e.target.result;
}
})(img);
有人只是决定变得有点聪明,并编写了一个 IIFE,它在每次迭代中锁定 img
的值,并带有一个返回函数的 IIFE。
换句话说,如果他们只是在没有 IIFE 的情况下引用它,他们最终只会得到最后一个 img
,因为 for 循环会完成并覆盖 img
变量在每次迭代中,当循环完成并且 img
仅保存最后一个值集时,onload 函数稍后执行。
关于javascript - 为什么 FileReader.onload 处理程序设置了自执行函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24661030/