遵循代码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; };
答案 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
仅保存最后一个值时。