Warum ist das FileList-Objekt kein Array?

76

Dokumentation: https://developer.mozilla.org/en-US/docs/Web/API/FileList

Warum ist FileListein Objekt eher ein Array als ein Array? Die einzige Eigenschaft, die es hat, ist .lengthund die einzige Methode, die es hat .item(), ist redundant ( fileList[0] === fileList.item(0)).

Vladimir Kornea
quelle
2
Viele APIs, die sich auf DOM und HTML beziehen, sind datenstrukturunabhängiger definiert. Denken Sie an NodeLists und HTMLCollections. Was ist beispielsweise, wenn eine Sprache die foo[bar]Syntax nicht unterstützt ?
Felix Kling

Antworten:

89

Nun, es kann mehrere Gründe geben. Zum einen könnten Sie ein Array ändern, wenn es sich um ein Array handelt. Sie können eine FileListInstanz nicht ändern . Zweitens, aber verwandt, könnte es sich (wahrscheinlich) um eine Ansicht einer Browser-Datenstruktur handeln, sodass ein minimaler Satz von Funktionen es für Implementierungen einfacher macht, diese bereitzustellen.

Sie können es über a = Array.from(theFileList)(das ist eine ES2015-Methode, aber es ist trivial, es zu füllen) oder über in ein Array konvertieren a = Array.prototype.slice.call(theFileList).

Update im Jahr 2018: Interessanterweise enthält die Spezifikation jedoch einen Hinweis zu FileList:

Die FileListSchnittstelle sollte als "gefährdet" eingestuft werden, da der allgemeine Trend auf der Webplattform darin besteht, solche Schnittstellen durch das ArrayPlattformobjekt in ECMAScript [ECMA-262] zu ersetzen . Dies bedeutet insbesondere, dass die Syntax dieser Art filelist.item(0)gefährdet ist. Die meisten anderen programmatischen Anwendungen von FileListwerden wahrscheinlich nicht von der eventuellen Migration zu einem ArrayTyp beeinflusst.

Ich finde diese Notiz seltsam. Ich dachte, der Trend geht in Richtung iterable, nicht Array - wie das Update, um NodeListes iterablefür die Kompatibilität mit der Spread-Syntax zu markieren for-of, und forEach.

TJ Crowder
quelle
4
Da Sie es nicht ändern können, gibt es keinen Grund dafür .push()und andere Array-Methoden.
Vladimir Kornea
@VladimirKornea (die Zeit vergeht, aber ...) Nun, ich habe den Anwendungsfall der Validierung von Dateigrößen, daher ist "Filter" von Array praktisch. Es gibt viele andere "schreibgeschützte" Methoden.
Estani
11

Ich denke, es ist ein eigener Datentyp, weil objektorientierte Programmierung mehr eine Sache war als funktionale Programmierung, als sie definiert wurde. Modernes Javascript bietet Funktionen zum Umwandeln von Array-ähnlichen Datentypen in Arrays.

Zum Beispiel wie Tim beschrieben: const files = [...filesList]

Eine andere Möglichkeit, eine FileList mit ES6 zu iterieren, ist die Array.from () -Methode.

const fileListAsArray = Array.from(fileList)

IMO ist es besser lesbar als der Spread-Operator, aber andererseits ist es längerer Code :)

Valentin Rapp
quelle
6

Wenn Sie Array-Methoden für FileList verwenden möchten, versuchen Sie es apply

Also zum Beispiel:

Array.prototype.every.call(YourFileList, file => { ... })

wenn du jeden benutzen willst

machnicki
quelle
0

Hier sind einige Polyfills, die eine toObject()Funktion Fileund eine toArray()Funktion hinzufügen 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()
Kodie Grantham
quelle