Чому об’єкт FileList не є масивом?


77

Документація: https://developer.mozilla.org/en-US/docs/Web/API/FileList

Чому це FileListоб’єкт, а не масив? Єдина властивість, яку він має, - .lengthце єдиний метод .item(), який є надлишковим ( fileList[0] === fileList.item(0)).


2
Багато API, пов’язані з DOM і HTML, визначаються більш структурно-агностично. Подумайте про NodeLists і HTMLCollections. Наприклад, що, якщо мова не підтримує foo[bar]синтаксис?
Фелікс Клінг,

Відповіді:


93

Ну, причин може бути кілька. По-перше, якби це був масив, ви могли б його змінити. Ви не можете змінити FileListекземпляр. По-друге, але пов’язано, це може бути (можливо, є) перегляд структури даних браузера, тому мінімальний набір можливостей полегшує реалізацію його надання.

Ви можете перетворити його в масив через a = Array.from(theFileList)(це метод ES2015, але тривіально його заповнити) або через a = Array.prototype.slice.call(theFileList).

Оновлення у 2018 році: Що цікаво, однак у специфікації є примітка про FileList:

FileListІнтерфейс слід розглядати як « групи ризику» , так як загальна тенденція на веб - платформі, щоб замінити такі інтерфейси з Arrayоб'єктом платформи в ECMAScript [ECMA-262]. Зокрема, це означає, що такий синтаксис filelist.item(0)піддається ризику; на більшість інших програмних застосувань FileList, навряд чи вплине можливий перехід на Arrayтип.

Я вважаю цю записку дивною. Я думав, що тенденція спрямована на iterable, а не на Array зразок оновлення для NodeListпозначення його iterableдля сумісності із синтаксисом поширення for-of, та forEach.


5
Оскільки ви не можете змінити його, немає жодних причин для цього .push()та інших методів масиву.
Володимир Корнеа

@VladimirKornea (час минає, але ...) ну, у мене є варіант використання перевірки розмірів файлів, тому "фільтр" від Array стане в нагоді. Існує багато інших методів "лише для читання".
estani

Чи означає примітка, що її буде ризиковано використовувати Array.from(theFileList)? Спасибі за вашу допомогу!
Крашалот

@Crashalot - Ні, це повинно бути добре. Я не можу FileListсобі уявити , що він зникає (хоча я можу помилитися - як зазначається в примітці, код більшості людей трактує це як масив), але, мабуть, itemметод може, оскільки він широко не використовується. Але об’єкт буде там і буде схожий на масив, тож Array.from(theFileList)ви перейдете від можливо мінливої ​​речі ( FileList) до гарної чітко визначеної речі (масиву).
TJ Crowder

Дякуємо за швидку реакцію та роз'яснення. Добре, ми будемо дотримуватися використання, Array.from(theFileList)оскільки це не справжній масив, і він нам потрібен як масив для цілей конкатенації.
Крашалот

12

Я думаю, що це його власний тип даних, оскільки об’єктно-орієнтоване програмування було більше речей, ніж функціонального програмування, коли воно було визначене. Сучасний Javascript пропонує функціональність для передавання типів даних, схожих на масив, до масивів.

Наприклад, як описано Тімом: const files = [...filesList]

Іншим способом ітерації FileList за допомогою ES6 є метод Array.from ().

const fileListAsArray = Array.from(fileList)

IMO він читабельніший, ніж оператор поширення, але з іншого боку це довший код :)


6

Якщо ви хочете використовувати методи масивів у FileList, спробуйте apply

Так наприклад:

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

якщо ви хочете використовувати кожну


0

Ось пара поліфілів, які додають toObject()функцію до Fileта toArray()функцію до 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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.