正如@chazsolo 提到的:
有一种感觉,这将是由于您在循环中使用了 img 造成的。由于 reader.onload 是异步的,因此 for 循环已经完成,并且 img 指向最后一个
您可以使用以下方法修复此问题let
代替var
在循环内(让-MDN) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let。这将给每个img
and reader
循环内的块作用域,允许异步读取器方法仍然访问该特定循环运行的实际值。
window.ondragover = function(e){return false;}
window.ondragenter = function(e){return false;}
window.ondrop = function(e){
var files = e.target.files || e.dataTransfer.files;
debugger;
for (var i = 0, file; file = files[i];i++){
let img = document.createElement('img');
img.height = 200;
img.width = 200;
img.style.background = 'grey';
document.body.appendChild(img);
let reader = new FileReader();
reader.onload = function(){
img.src = reader.result;
}
reader.readAsDataURL(file);
}
return false;
}
更新:var 与 let
那么为什么它没有像怀疑的那样工作var
?
我尝试解释一下两者的区别let
and var
一些实际的例子。
变量声明,无论它们出现在哪里,都会在任何变量声明之前进行处理
代码被执行。
这导致我们看到以下示例(不要介意最后的错误,该错误是由片段插件产生的):
用 var 声明
/**
In this example, 'a' is declared after it is used. This doesn't matter, as the
declaration of 'a' will be processed before running the code. This means a is
initialized with 'undefined' but is valid. Also the scope of a lies within the
execution context, that's why it is even available outside of the loop.
**/
console.log("---------");
console.log("Example Declaration var");
console.log("---------");
for (var i = 0; i < 2; i++) {
console.log(a); // a is declared but undefined on the 1st run, afterwards it get redeclared and owns the value from the last run.
var a = i;
}
console.log(a); // a is even available out here as still same execution context.
We see, that on every re declaration of
a
the value of the
a
before, is kept. It is not a new "instance".
那么如果我们在循环中使用异步函数会发生什么?
带 var 的异步函数
/**
This example shows you the effects, if you use a async function within a loop.
As the loop will be executed way under 100 miliseconds (which is the time out
of the async function), c will have the same value for all exections of the
async mehtod, which is the value assigned by the last run of the loop.
**/
console.log("---------");
console.log("Example effects async var");
console.log("---------");
for (var i = 0; i < 2; i++) {
var c = i;
setTimeout(function() {
console.log(c); //var does redeclare, therefor c will be modified by the next loop until the last loop.
}, 100);
}
完全相同,始终相同的输出(适应您的问题,始终相同的 img 元素和文件)
让我们看看发生了什么let
用 let 声明
/**
In this example, 'b' is declared after it is used with let. let will be processed
during runtime. This means 'b' will not be declared when used. This is an invalid
state. let will give a strict context within the loop. It will be not available
outside. let has a similar behavior as a declaration in Java.
**/
console.log("---------");
console.log("Example Declaration let");
console.log("---------");
for (var i = 0; i < 2; i++) {
try {
console.log(b); //b is not declared yet => exception
} catch (ex) {
console.log("Exception in loop=" + ex);
}
let b = i;
console.log("Now b is declared:"+b);
}
try {
console.log(b); // b is not available out here as the scope of b is only the for loop. => exception
} catch (ex) {
console.log("Exception outside loop=" + ex);
}
console.log("Done");
A lots of exceptions are thrown, as
let
has a more specific scope. Which leads to more intentional coding.
最后,我们看看当我们使用时会发生什么let
以及循环内的异步函数。
带 let 的异步函数
/**
This example shows you the effects, if you use a async function within a loop.
As the loop will be executed way under 100 milliseconds (which is the time out
of the async function). let declares a new variable for each run of the loop,
which will be untouched by upcoming runs.
**/
console.log("---------");
console.log("Example effects async let");
console.log("---------");
for (var i = 0; i < 2; i++) {
let d = i;
setTimeout(function() {
console.log(d); //let does not redeclare, therefor d will not be modified by the next loop
}, 100);
}
结论
在你的例子中,你总是最终得到最后分配的img
元素和最后分配的file
。您执行相同操作的次数与数组中最后一个文件的文件数相同。