Why isn't the FileList object an array?
Solution 1:
Well, there could be several reasons. For one, if it were an array, you could modify it. You can't modify a FileList
instance. Secondly but related, it could be (probably is) a view onto a browser data structure, so a minimal set of capabilities makes it easier for implementations to provide it.
You can convert it to an array via a = Array.from(theFileList)
(that's an ES2015 method, but it's trivial to polyfill it) or via a = Array.prototype.slice.call(theFileList)
.
Update in 2018: Interestingly, though, the spec has a note on FileList
:
The
FileList
interface should be considered "at risk" since the general trend on the Web Platform is to replace such interfaces with theArray
platform object in ECMAScript [ECMA-262]. In particular, this means syntax of the sortfilelist.item(0)
is at risk; most other programmatic use ofFileList
is unlikely to be affected by the eventual migration to anArray
type.
I find that note odd. I thought the trend was toward iterable
, not Array
— such as the update to NodeList
marking it iterable
for compatibility with spread syntax, for-of
, and forEach
.
Solution 2:
I think it's its own Datatype because Object Oriented Programming was more of a thing than functional programming back when it was defined. Modern Javascript offers functionality to cast Array-like Datatypes to Arrays.
For example, like Tim described:
const files = [...filesList]
Another way of iterating a FileList with ES6 is the Array.from() method.
const fileListAsArray = Array.from(fileList)
IMO it's more readable than the spread operator, but on the other hand it's longer code :)
Solution 3:
If you want use array methods on FileList try apply
So for example:
Array.prototype.every.call(YourFileList, file => { ... })
if you want to use every
Solution 4:
Here's a couple of polyfills that add a toObject()
function to File
and a toArray()
function to FileList
:
File.prototype.toObject = function () {
return Object({
lastModified: parseInt(this.lastModified),
lastModifiedDate: String(this.lastModifiedDate),
name: String(this.name),
size: parseInt(this.size),
type: String(this.type)
})
}
FileList.prototype.toArray = function () {
return Array.from(this).map(function (file) {
return file.toObject()
})
}
var files = document.getElementById('file-upload').files
var fileObject = files[0].toObject()
var filesArray = files.toArray()