[英]Unexpected result when using For Loop instead of forEach
我正在尝试迭代输入中的选定文件,当我切换以下语句时,我遇到了一个奇怪的错误
Object.keys(event.target.files).forEach(key => {
const currentFile = event.target.files[key]
}
至
for (let key in event.target.files) {
const currentFile = event.target.files[key]
}
我不明白这两个语句之间有什么区别,第一个有效,但第二个无效(导致奇怪的错误,循环内的 object 变为 null。
这是完整的代码:
onChange= (event) => {
const selectedFilesObject = event.target.files
let selectedFilesCount = Object.keys(selectedFilesObject).length
if (selectedFilesCount > 0) {
this.setState({ loading: true })
this.props.onLockdownChange(true)
let readFilesResult = {}
for (let key in selectedFilesObject) {
const currentFile = selectedFilesObject[key]
readFileAsByteArray(currentFile)
.then(response => {
readFilesResult[key] = {
bytes: response,
name: currentFile.name,
type: currentFile.type,
}
})
.catch(() => {
readFilesResult[key] = null
})
.finally(() => {
selectedFilesCount = selectedFilesCount - 1
if (selectedFilesCount === 0) {
this.onReadingFilesFinished(readFilesResult)
}
})
}
}
}
export const readFileAsByteArray = (file) => {
return new Promise((resolve, reject) => {
var reader = new FileReader();
var fileByteArray = [];
reader.readAsArrayBuffer(file);
reader.onloadend = (evt) => {
if (evt.target.readyState == FileReader.DONE) {
var arrayBuffer = evt.target.result,
array = new Uint8Array(arrayBuffer);
for (var i = 0; i < array.length; i++) {
fileByteArray.push(array[i]);
}
resolve(fileByteArray)
}
}
reader.onerror = error => {
reject()
};
})
}
我只需要了解为什么使用 for 循环会导致readFilesResult
具有 null 长度! 但使用object.keys().forEach
不会!
您在这里枚举了一个FileList
,它作为一个 DOM 集合具有item
和length
属性。 您不应该在此处使用Object.keys
或for … in
循环,而应像在任何类似数组的 object 上那样使用for (let i=0; i<files.length; i++)
迭代。 另请参阅为什么在 arrays 上使用for…in
是个坏主意? .
或者直接将其转换为数组:
onChange = (event) => {
const selectedFiles = Array.from(event.target.files)
// ^^^^^^^^^^
if (selectedFiles.length > 0) {
this.setState({ loading: true })
this.props.onLockdownChange(true)
Promise.all(selectedFiles.map(currentFile =>
readFileAsByteArray(currentFile).then(response => ({
bytes: response,
name: currentFile.name,
type: currentFile.type,
}), err => null)
)).then(readFilesResult => {
this.onReadingFilesFinished(readFilesResult)
})
}
}
这两个循环之间的区别归结为 object 是否实际上具有属性,或者继承了属性。
例如,如果您有一个继承了属性的 object; Object.keys
不会返回它,但 for in 循环会。 这就是为什么您需要为 for in 循环中的每个键调用hasOwnProperty
方法。
以更详细的方式; for in 循环不受原型链的困扰。
// lets create a class called "Example".
class Example{
constructor(a,b) {
this.a = a;
this.b = b;
}
}
let instance = new Example(1,2);
for(let key in instance) {
console.log(key); // will only print "a" and "b". Which is to be expected.
}
// Let's add a member to all of the objects that are instantiated from the class Example using Example's prototype.
Example.prototype.newMember = "I exist";
// Let's run the for in loop again
for(let key in instance) {
console.log(key); // Prints "a", "b", and "newMember". The instances that are coming from "Example" doesn't have this... What happened there?
}
结果是,当您运行 for-in 循环时,该循环无法识别原型属性,并在所有这些属性上运行。 这就是为什么我建议对您的示例运行hasOwnProperty
检查。 hasOwnProperty
检查该成员是否确实具有属性,或者它是否是原型属性。
这有任何意义吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.