標準とWebkitソースコードに従ってDOMを探究--要素のgetElementsByClassNameを取得

3892 ワード

要素をクラス名で取得--getElementsByClassName(HTML 5)
標準
  • WHATWGはDocumentElementに定義されており、プロトタイプHTMLCollection getElementsByClassName(DOMString classNames)はマッチングアルゴリズムとクラス名の抽出アルゴリズムを定義している.ここではパラメータからクラス名を1つのsetとして抽出してからマッチングを開始することに注意する.ここではquirks modeの下でクラス名の大文字と小文字が敏感でないことを示し、そうでない場合、大文字と小文字が敏感である
  • DOM 4(DocumentElement)は基本的にWHATWGと一致する
  • である.
    注意点
    標準的に言えば、「Unless otherwise stated,a collection must be live.」です.getElementsByClassNameの戻り値がstaticであることが標準で示されていない以上、HTMLCollectionがliveである.
    WHATWG記述getElementsByClassNameの実装は,まずパラメータからASCII空白文字でクラス名を分割し,得られたクラス名を1つの秩序ある集合を構成した後,集合内のすべてのクラス名に一致する要素を返す.quirks modeでない限り、大文字と小文字は敏感であり、DocumentおよびElementに定義されている.
    互換性
  • はHTML 5に新しく登場したAPIに属し、IE 9+およびその他のブラウザの現行バージョンは
  • をサポートしている.
    WebKitコード解析
    従来のいくつかの方法と同様に,ContainerNodeで実現され,ClassNodeListNodeListsNodeData::addCacheWithAtomicName<>のtemplate specializationとして用いた.前回commitはnodeMatcheselementMatchesに変更しましたが、githubのmirrorではClassNodeListはまだ変更されていないようです.ClassNodeListnodeMatchesフィルタ基準(WebCore/dom/ClassNodeList.h参照)は、次のとおりです.
    if (!element->hasClass())
        return false;
    if (!m_classNames.size())
        return false;
    // FIXME: DOM4 allows getElementsByClassName to return non StyledElement.
    // https://bugs.webkit.org/show_bug.cgi?id=94718
    if (!element->isStyledElement())
        return false;
    return element->classNames().containsAll(m_classNames);

    中には現在、余分なStyledElementが判定されているのが見えますが...ここではまず、フィルタリングする要素にclassがあるかどうか、または入力された文字列に有効なclassが含まれていないかどうかを判断し、次に要素がStyledElementであるかどうかをチェックします(関連ドキュメントは見つかりませんが、Node.hのenum ConstructionTypeでは、どの要素がStyledElementであるかを見ることができます).
    クラス名の抽出はSpaceSplitStringで実現される.ClassNodeListおよびElementDataは、クラス名の集合を維持するために SpaceSplitStringm_classNamesである.これらの外部のクラスは、SpaceSplitString::setを呼び出すことによってクラス名を更新および設定し、SpaceSplitString::setは、SpaceSplitStringData::createを呼び出すことによって、セットが格納されたプライベートメンバーSpaceSplitStringData m_dataを維持する.SpaceSplitStringData::createには2つのリロードがあり、外部から呼び出されたのはSpaceSplitStringData::create (const AtomicString& keyString)です.まず、メンテナンスキャッシュのspaceSplitStringTable(実質的にstaticのhashmap)を呼び出して、キャッシュがすでに存在するかどうかを確認し、存在しない場合はセットの作成を開始します.WebCore/dom/SpaceSplitString.cppのtokenizeSpaceSplitStringはクラス名文字列tokenizeのアルゴリズムを実現し、tokenを分解するたびにパラメータtokenProcessorprocessTokenを呼び出す.SpaceSplitStringData::create (const AtomicString& keyString)まずTokenCountertokenProcessorとしてtokenizeSpaceSplitStringを呼び出し、クラス名文字列をまず統計token数をスキャンしてメモリの割り当てを容易にし、次にリロードされたSpaceSplitStringData::create(const AtomicString& keyString, unsigned tokenCount)を呼び出し、TokenAtomicStringInitializertokenProcessorとしてもう一度文字列をスキャンし、各tokenの内容を割り当てられたメモリに保存する.
    マッチングを判断するアルゴリズムは乱暴だ......WebCore/dom/SpaceSplitStringを参照.cppのcontainsAllとWebCore/dom/SpaceSplitString.hのcontainsでは、意外にも線形ルックアップセット線形ルックアップのO(mn)(mとnはそれぞれ検索するクラス名と検索される要素の実際のクラス名)であることがわかりますが...アプリケーションシーンでは一般的なクラス名が少なく、多点でも5、6個であることを考慮すると、検索されるクラス名はもっと少ないかもしれませんが、mnを乗じるとせいぜい2、30程度かもしれませんが、一般的には10を超えません.この場合、高度なデータ構造によるoverheadは、単純な線形検索よりも大きい可能性があるため、このように実現するのも合理的である.