jQueryが諸事情で使えない(というか外部ライブラリ全般ページに呼び込みたくない)案件があって、document.querySelectorAll('.nyan')
でとれたDOMの中から(プログラム上)任意のdata値のvalueだけを持つものが欲しい時があり、少し面倒だったので忘備録。
<ul>
<li class="nyan" data-nyan="1">nyan</li>
<li class="nyan" data-nyan="2">nyan :)</li>
<li class="nyan" data-nyan="3">nyan :(</li>
<li class="nyan" data-nyan="4">nyan ;)</li>
<li class="nyan" data-nyan="5">nyan ;(</li>
</ul>
上記のDOMから data-nyan
が 3の値が欲しい場合、
const nyans = document.querySelectorAll('.nyan');
const resultNyan = nyans.filter((element, index) => {
return element.dataset['nyan'] === '3';
});
// Error => Uncaught TypeError: nyans.filter is not a function
と怒られてしまう。
どうやらNodeListには列挙したりするイテレータはあるものの、特定の要素をつまみ出すようなメソッドは備わってないとのこと。
ということで、純粋にNodeListに対してfilterを使いたい場合、@type {NodeList} => {Array}
にしてやる必要がある。
const nyans = document.querySelectorAll('.nyan');
const convertedTypeArrayNyan = [].map.call(nyans, (element) => {
return element;
});
const resultNyan = convertedTypeArrayNyan.filter((element, index) => {
return element.dataset['nyan'] === '3';
});
// resultNyan[0].outerHTML: "<li class="nyan" data-nyan="3">nyan :(</li>"
とスッキリいく。
中には Array.prototype.slice.call
使ったりもあったが、「Arrayライクなリスト型のものを、Arrayとして再配列(マッピング)する」という意味では Array.prototype.map
のほうがしっくり来たのでこっちを使っている(まぁNodeListの余分な物を削ぎ落とすってことでsliceも考えられなくはないが)。
ということでNodeListでListなんだから、もう少しそこら辺のメソッド拡張してよEcmaさんって雑な感想をもった。