1. ホーム
  2. ジャバスクリプト

[解決済み] JavaScriptのNodeListをArrayに変換する最速の方法は?

2022-04-15 15:23:26

質問

過去に回答した質問では、この方法が一番早いと書いてありました。

//nl is a NodeList
var arr = Array.prototype.slice.call(nl);

私のブラウザでベンチマークをとったところ、この3倍以上遅いことが判明しました。

var arr = [];
for(var i = 0, n; n = nl[i]; ++i) arr.push(n);

どちらも同じ出力をしますが、私の2番目のバージョンが最速の方法であるとは信じがたく、特にここでそうではないと言われているためです。

これは私のブラウザ(Chromium 6)のクセなのでしょうか?それとも、もっと速い方法があるのでしょうか?

EDIT: 気になる人のために、私は以下に落ち着きました(私がテストしたすべてのブラウザで最速のようです)。

//nl is a NodeList
var l = []; // Will hold the array of Node's
for(var i = 0, ll = nl.length; i != ll; l.push(nl[i++]));

EDIT2: もっと早い方法を見つけました。

// nl is the nodelist
var arr = [];
for(var i = nl.length; i--; arr.unshift(nl[i]));

解決方法は?

2021年版を更新しました。 nodeList.forEach()が標準化されました。 で、現在のすべてのブラウザでサポートされています ( モバイルでは約95%。 ).

だから、単純にできるんです。

document.querySelectorAll('img').forEach(highlight);


その他の事例

何らかの理由で、単に反復処理するだけでなく、配列に変換したい場合 - これは完全に関連するユースケースです - は、次のようにします。 [...destructuring] または Array.from ES6以降

let array1 = [...mySetOfElements];
// or
let array2 = Array.from(mySetOfElements);

これは、NodeList ではない他の配列のような構造でも動作します。

  • HTMLCollection などで返されます。 document.getElementsByTagName
  • 長さプロパティとインデックス付き要素を持つオブジェクト
  • 反復可能なオブジェクト(例えば MapSet )



2010年の古い回答

2番目のものは、一部のブラウザで高速化する傾向がありますが、1番目のものはクロスブラウザに対応していないため、使用する必要があるというのが大きなポイントです。たとえ、The Times They Are a-Changin'(時代と共に去りぬ)であっても。

カンガックス ( IE 9プレビュー )

Array.prototype.slice が変換できるようになりました。 特定のホストオブジェクト(例:NodeList's) を配列に変換します。 モダンブラウザでできるようになった を追加しました。

Array.prototype.slice.call(document.childNodes);