最近FileAPIを使うことがあり、
「FileList
ってArray
と似たようなもんやろ!!!!!」(forEach
ッターン!!!)
ってやったら見事に動かなかったので拡張した話を書きます。
そもそもFileListってなにができんの
MDNを見ると。
https://developer.mozilla.org/ja/docs/Web/API/FileList
この型のオブジェクトは、
<input>
要素のfiles
プロパティによって返されます;これによって、<input type="file">
要素で選択されたファイルのリストにアクセスできます。
ここだけ読むと完全に「Array
継承してんじゃねこれ?」って感じがある。
読み進めると。
メソッドが一つしかない。
なんでや。
ブラウザのコンソールで確認。
なんでや!
forで回すのなんて嫌や!!
いろいろ拡張してやる!!
拡張する
単純にprototype
に追加していけばいい感じになるはず。
FileList.prototype.reduce = function(fun, initialValue){
var result = initialValue;
for(i = 0; i < this.length; i++){
result = fun(result, this[i]);
}
return result;
}
たぶんこんな感じ。
ですが、Array
でreduce
が実装されてんだし、自分でわざわざ実装しなくてもいい気がするんだよなー。と僕は思いました。
なので、
FileList.prototype.reduce = function(){
return Array.prototype.reduce.call(this, ...arguments)
}
こうした。
ブラウザによっては動かないかもしれないが、Chromeでは動いた。
ほかのmap
等も同じようにやってけば
FileList
でArray
のメソッドを使えるようになると思う。
push
とかは無理だと思う。
現場からは以上です。
追記
@think49 さんにコメントを頂きました!
http://qiita.com/merotan/items/1b94ba43c26a6c370661#comment-11fe5cf1b1d81087e017
未検証ですが、Array.prototype.reduce の仕様を読む限りでは「故意に汎用的に」定義されているように見えますので下記コードでいい気がします。
22.1.3.18 Array.prototype.reduce ( callbackfn [ , initialValue ] ) – ECMA-262 6th Edition
FileList.prototype.reduce = Array.prototype.reduce;
ただし、上記方法及び本記事で紹介されている方法はいわゆる**prototype汚染を誘発する**ので Object.defineProperty で {enumerable: false} を指定するとベターです。
`Object.defineProperty`でやってみた。
```js
Object.defineProperty(FileList.prototype, 'reduce', {
value: Array.prototype.reduce,
enumerable: false
});
こうすると良さそう。