JavaScriptでDOMをDFSする4つの書き方
はじめに
DOM(Document Object Model)のDFS(深さ優先探索)をする場合、再帰関数を使う普通の書き方をしています。
再帰関数を使わないでDOMのDFSを書けることは有名ですが、DOMが子要素や兄弟要素へのリンクを持つ特性を利用することによって、配列も再帰関数も使わないで書けます。
コメントで知った方法と合わせて4つの書き方があることを紹介します。
それぞれの時間を計測したら意外な結果になりました。
4通りの書き方
4つのJavaScriptプログラムは一文字命名規則を使っています。
dfs_1
普通は再帰関数で書きます。
var dfs_1 = (e_base) => {
var e_children = e_base.children;
for (let index = 0; index < e_children.length; index++) {
const e_child = e_children[index];
dfs_1(e_child);
}
};
dfs_2
配列に状態を保存することによって再帰関数を使わないで書けます。
var dfs_2 = (e_root) => {
var e_focus;
var d_dfs = [e_root];
while (d_dfs.length) {
e_focus = d_dfs.shift();
if (e_focus.children.length) {
d_dfs.unshift(...e_focus.children);
}
}
};
dfs_3
DOMが子要素(firstElementChild
)や兄弟要素(nextElementSibling
)へのリンクを持つ特性を利用することによって実は配列も再帰も使わないで書けます。
どのように書けば良いでしょうか?
頭の体操です。正解を折りたたみで隠しますので少し考えてみてください。
再帰も配列も使わない書き方
var dfs_3 = (e_root) => {
var e_focus = e_root;
outer: while (true) {
if (e_focus.firstElementChild) {
e_focus = e_focus.firstElementChild;
continue;
}
while (true) {
if (e_focus == e_root) {
break outer;
} else if (e_focus.nextElementSibling) {
e_focus = e_focus.nextElementSibling;
continue outer;
} else {
e_focus = e_focus.parentElement;
}
}
}
};
dfs_4
Web API のcreateTreeWalkerでも書けます。
MDN Web Docs には DFS という説明がありませんが DFS のようです。
var dfs_4 = (e_root) => {
var t_root = document.createTreeWalker(e_root, NodeFilter.SHOW_ELEMENT);
var e_focus = t_root.currentNode;
while (e_focus) {
e_focus = t_root.nextNode();
}
};
時間計測
時間を計測してみました。
dfs | 時間(msec) |
---|---|
dfs_1 | 23.7 |
dfs_2 | 91.0 |
dfs_2b | 79.7 |
dfs_3 | 12.8 |
dfs_4 | 5.7 |
メソッド push/pop は処理が速く、shift/unshift は遅いです。
というのを見つけて shift/unshif を push/pop に変えたプログラムがdfs_2bです。
さいごに
dfs_1 > dfs_2 > dfs_3 と予想していたので意外な結果になりました。
JavaScriptで配列を使うくらいなら再帰関数のままで良い、と言えそうです。
shift/unshift を push/pop に変えても少しだけ速くなりましたが、そもそも配列を使うことが遅くする、と言えそうです。
dfs_4 はシンプルで可読性が高く最速です。Web API が存在するなら Web API を使いましょう。
Author And Source
この問題について(JavaScriptでDOMをDFSする4つの書き方), 我々は、より多くの情報をここで見つけました https://qiita.com/querykuma/items/cb11a2afe9ea008be972著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .