1. ホーム
  2. javascript

[解決済み] textNodesのgetElementsByTagName()の等価性

2023-05-15 05:15:53

質問

すべての textNode オブジェクトのコレクションを取得する方法はありますか?

getElementsByTagName() はElementsのために素晴らしく働きますが textNode は要素ではありません。

更新しました。 私はこれがDOMを歩くことによって達成されることができることを理解します - 以下の多くの提案があるように。私は、ドキュメント内のすべてのノードを見る DOM-walker 関数を書く方法を知っています。私はそれを行うためにいくつかのブラウザネイティブの方法があることを望んでいました。結局のところ、私がすべての <input> を 1 回の組み込み呼び出しで取得できるのに、すべての textNode s.

どのように解決するのですか?

更新 :

これらの6つのメソッドについて、それぞれ1000回の実行による基本的な性能テストの概要を示しました。 getElementsByTagName は最も高速ですが、すべての要素を選択するのではなく、ある特定のタイプのタグだけを選択するので、中途半端な仕事しかしていません ( p を選択し、そのfirstChildがtext要素であることを盲目的に仮定しています。これは少し欠点があるかもしれませんが、デモンストレーションのためであり、そのパフォーマンスを TreeWalker . jsfiddleでテストを実行する を実行し、その結果をご覧ください。

  1. TreeWalkerを使用する
  2. カスタムの反復的トラバーサル
  3. カスタム再帰的探索
  4. Xpath クエリ
  5. クエリセレクターオール
  6. getElementsByTagName

仮に、すべての Text ノードをネイティブに取得できるメソッドがあると仮定します。それでも、結果のテキストノードをそれぞれ走査して node.nodeValue を呼び出して実際のテキストを取得する必要があります。したがって、パフォーマンスの問題は、テキスト ノードの反復処理ではなく、テキスト以外のすべてのノードの反復処理とその型のチェックにあります。私は(結果に基づいて)、このように TreeWalker と同じように高速に動作する getElementsByTagName と同じくらい高速に動作します(getElementsByTagNameがハンディキャップを負っている場合でも)。

各テストを1000回ずつ実行しました。

方法 合計 ms 平均 ms
--------------------------------------------------
document.TreeWalker 301 0.301
反復的トラバーサ 769 0.769
再帰的トラバーサ 7352 7.352
XPath クエリ 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212


各メソッドのソースです。

ツリーウォーカー

function nativeTreeWalker() {
    var walker = document.createTreeWalker(
        document.body, 
        NodeFilter.SHOW_TEXT, 
        null, 
        false
    );

    var node;
    var textNodes = [];

    while(node = walker.nextNode()) {
        textNodes.push(node.nodeValue);
    }
}

再帰的木構造走査

function customRecursiveTreeWalker() {
    var result = [];

    (function findTextNodes(current) {
        for(var i = 0; i < current.childNodes.length; i++) {
            var child = current.childNodes[i];
            if(child.nodeType == 3) {
                result.push(child.nodeValue);
            }
            else {
                findTextNodes(child);
            }
        }
    })(document.body);
}

反復的な木の探索

function customIterativeTreeWalker() {
    var result = [];
    var root = document.body;

    var node = root.childNodes[0];
    while(node != null) {
        if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */
            result.push(node.nodeValue);
        }

        if(node.hasChildNodes()) {
            node = node.firstChild;
        }
        else {
            while(node.nextSibling == null && node != root) {
                node = node.parentNode;
            }
            node = node.nextSibling;
        }
    }
}

クエリセレクターオール

function nativeSelector() {
    var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
    var results = [];
    var child;
    for(var i = 0; i < elements.length; i++) {
        child = elements[i].childNodes[0];
        if(elements[i].hasChildNodes() && child.nodeType == 3) {
            results.push(child.nodeValue);
        }
    }
}

getElementsByTagName (ハンディキャップ)

function getElementsByTagName() {
    var elements = document.getElementsByTagName("p");
    var results = [];
    for(var i = 0; i < elements.length; i++) {
        results.push(elements[i].childNodes[0].nodeValue);
    }
}

XPath

function xpathSelector() {
    var xpathResult = document.evaluate(
        "//*/text()", 
        document, 
        null, 
        XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
        null
    );

    var results = [], res;
    while(res = xpathResult.iterateNext()) {
        results.push(res.nodeValue);  /* Fixed a bug here. Thanks @theazureshadow */
    }
}

また、この議論は参考になるかもしれません -。 http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node