JavaScript で再帰呼び出しを使わずに文書ツリーを辿る例
JavaScript で文書ツリーを辿るコード例
再帰呼び出しは、短く書け読みやすいのですが、関数を多段で呼び出すコストが発生します。パフォーマンスの求められるところでは不適当です。本記事では再帰呼び出しをせずに、一度の関数呼び出しと do~while
ループでノードツリーを辿る例を紹介します。
次の例では、与えらえたノード自身を引数に onReachNode
関数をコールバックします。以降は、最初に見つかった子ノードから同様にコールバックしていきます。
コールバックで true
を返すと探索を終了します。コールバック中に現在のノードより前方にノードを挿入したり、前方のノードを除去すると index が乱れて正しく動作しません。
function walkAllDescendantNodes(node, onReachNode){
var depthX2 = 0,
childNodes = [node],
combiList = [-1, childNodes],
child, childsChildNodes;
do {
child = childNodes[++combiList[depthX2 + 0]];
if (!child) {
combiList.length = depthX2;
depthX2 -= 2;
childNodes = combiList[depthX2 + 1];
} else {
if (onReachNode(child) === true) {
break;
};
childsChildNodes = child.childNodes;
if (childsChildNodes && childsChildNodes.length) {
depthX2 += 2;
combiList[depthX2 + 0] = -1;
combiList[depthX2 + 1] = childNodes = childsChildNodes;
};
};
} while (0 <= depthX2);
};
.nextSiblings
, .firstChild
を使って全てのノードを辿る方法も考えられます。しかし今回は、Virtual DOM で使うコードの切り出しの為、Array
で実装されている childNodes
を利用する方が低コストという判断でした。
生 DOM では .nextSiblings
, .firstChild
を使う方がハイパフォーマンスと思われます。
次のコードを加えて、ブラウザのデベロッパーコンソールで実行してみます。
walkAllDescendantNodes(
document,
function(node){
console.log(node.tagName || node.nodeValue || node.nodeType);
}
);
実行結果例です。全てのノードを辿れているようです。
9 10 HTML HEAD META LINK LINK META LINK TITLE クラウド番外地 META META . . .