querySelectorAllにforEachは使えない
document.querySelectorAllはCSS セレクタにマッチする文書中の要素のすべてのリストを返す。
例えば下記のように記述すればclass="foo"にテキストを挿入することができる。
1 2 3 4 | var el = document.querySelectorAll( '.foo' ); for ( var i=0; i<el.length; i++) { el[i].textContent = 'bar' + i; } |
forだと可読性が良くないためより簡単に記述するためforEachを使用しているコードをたまに見かける。
1 2 3 4 | var el = document.querySelectorAll( '.foo' ); el.forEach( function (el, i) { el.textContent = 'bar' + i; }); |
しかし、forEachを使用するとChrome以外のブラウザではエラーになり動作しない。
2018年9月追記: 最新バージョンのChromeでは動作するよう修正されている。
なぜならdocument.querySelectorAllで取得したものはオブジェクトでありforEachは配列の各要素に対して一度ずつ実行するためのメソッドだからだ。
よってChromeでエラーが出ないのは本来の仕様とは異なる。
1 2 3 4 5 | var el = document.querySelectorAll( '.foo' ); console.info( typeof el); // =>; object el.forEach( function (el, i) { el.textContent = 'bar' + i; }); |
しかしObject.keysとforEachを使用すれば処理できるので下記のように記述すればすべてのブラウザでエラーは発生しない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // before // <div class="hoge"></div> // <div class="hoge"></div> // <div class="hoge"></div> var el2 = document.querySelectorAll( '.hoge' ); Object.keys(el2).forEach( function (i) { el2[i].textContent = 'fuga' + i; }); // after // <div class="hoge">fuga0</div> // <div class="hoge">fuga1</div> // <div class="hoge">fuga2</div> // 用途によってはArray.fromが使える var el3 = document.querySelectorAll( '.bar' ); Array.from(el3).forEach((x, i) => x.textContent = 'bar' + i); |
ただし、iOS 9 Safariなどの古いブラウザだと前述の3つは使用できないため、ObjectではなくArrayに変換してからforeachを使用する必要がある。
1 2 3 4 5 | // iOS 9 Safariのような古いブラウザでも使用可能な書き方 var el0 = [].slice.call(document.querySelectorAll( '.baz' )); el0.forEach( function (el, i) { el.textContent = 'baz' + i; }); |
document.querySelectorAllにforEachを使用したサンプル