NodeListを配列に変換するのにArray.applyを使うのはどうか
NodeList
やHTMLCollection
を配列(Array
)に変換する方法の一つに、Array.prototype.slice
を使う方法がある。
var array = Array.prototype.slice.call(document.getElementsByTagName('A'));
でも、最近の実装であればArray.apply
もその用途に使える。
var array = Array.apply(null, document.getElementsByTagName('A'));
ES3ではFunction.prototype.apply
の第二引数には配列(Array
)かarguments
しか取れなかったけど、ES5でその制限が緩和され、NodeList
などの array like オブジェクトも渡せるようになった。
なお、IE8以下ではどちらの方法でもエラーになるので注意(エラーメッセージは「JScript オブジェクトを指定してください」)。ループで処理するしかない。
var array = []; var nodes = document.getElementsByTagName('A'); for (var i = 0, l = nodes.length; i < l; ++i) { array[i] = nodes[i]; }
ちなみに、arguments
の配列化にArray.apply
は使えない。arguments
は要素が単一の数値だけになる可能性があり、その場合意図しない結果になる。
(function () { var args = Array.apply(null, arguments); // Array(5, 6, 7) つまり [5, 6, 7] console.log(args.shift()); // 5 })(5, 6, 7); (function () { var args = Array.apply(null, arguments); // Array(5) つまり length: 5 の配列 console.log(args.shift()); // undefined })(5);
lengthが1でないことを確かめてからなら使える(参考:slice vs [].apply · jsPerf)けど、Array.prototype.slice
を使う方がシンプル。
(function () { var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments); console.log(args.shift()); // 5 })(5); (function () { var args = Array.prototype.slice.call(arguments); console.log(args.shift()); // 5 })(5);
おまけ:ES3実装およびIE8以下でFunction.prototype.apply
をES5仕様にするモンキーパッチ。