x.map is not a function
Author: 水卜
Author: 水卜
配列に対してmapしたはずなのに
x.map is not a function
と怒られることがある。
document.getElementsByTagName('h2').map(i => i.textContent);
> VM17827:1 Uncaught TypeError: document.getElementsByTagName(...).map is not a function at <anonymous>:1:37
この時mapを掛けようとした相手をよく見るとHTMLCollectionとある。
document.getElementsByTagName('h2');
> HTMLCollection(3) [h2, h2, h2]
スプレッド演算子を使ってこう書くと、配列を返してくれる。mapも使える。
[...document.getElementsByTagName('h2')].map(i => i.textContent);
iterable=反復可能。
for文でループできたり、スプレッド演算子で中身を展開できたりする。
以下詳細。
iterableプロトコル
つまりdocument.getElementsByTagNameの結果はiterableなオブジェクトではあるが、Arrayではない。
mapと呼んでいるメソッドは、正確にはArray.prototype.map()を指す。
prototypeはjsで継承を実現するときに使われる。
親クラスのprototypeに関数を定義し、子クラスのprototypeにスーパークラスのインスタンスを渡すと子は親の関数を引き継ぐ。
function Super() {}
Super.prototype.hello = 'hello';
var Sub = function() {}
Sub.prototype = new Super();
var instance = new Sub();
instance.hello // 10
つまり、Arrayを継承しているオブジェクトだけがmapを使うことができる。
冒頭の例でHTMLCollectionオブジェクトは、iterableではあるがArrayを継承していなかった。