標準とWebkitソースコードに従ってDOMを探究--要素のgetElementsByClassNameを取得
3892 ワード
要素をクラス名で取得--
標準 WHATWGは DOM 4( である.
注意点
標準的に言えば、「Unless otherwise stated,a collection must be live.」です.
WHATWG記述
互換性はHTML 5に新しく登場したAPIに属し、IE 9+およびその他のブラウザの現行バージョンは をサポートしている.
WebKitコード解析
従来のいくつかの方法と同様に,
中には現在、余分な
クラス名の抽出は
マッチングを判断するアルゴリズムは乱暴だ......WebCore/dom/SpaceSplitStringを参照.cppのcontainsAllとWebCore/dom/SpaceSplitString.hのcontainsでは、意外にも線形ルックアップセット線形ルックアップのO(mn)(mとnはそれぞれ検索するクラス名と検索される要素の実際のクラス名)であることがわかりますが...アプリケーションシーンでは一般的なクラス名が少なく、多点でも5、6個であることを考慮すると、検索されるクラス名はもっと少ないかもしれませんが、mnを乗じるとせいぜい2、30程度かもしれませんが、一般的には10を超えません.この場合、高度なデータ構造によるoverheadは、単純な線形検索よりも大きい可能性があるため、このように実現するのも合理的である.
getElementsByClassName
(HTML 5)標準
Document
とElement
に定義されており、プロトタイプHTMLCollection getElementsByClassName(DOMString classNames)
はマッチングアルゴリズムとクラス名の抽出アルゴリズムを定義している.ここではパラメータからクラス名を1つのsetとして抽出してからマッチングを開始することに注意する.ここではquirks modeの下でクラス名の大文字と小文字が敏感でないことを示し、そうでない場合、大文字と小文字が敏感であるDocument
Element
)は基本的にWHATWGと一致する注意点
標準的に言えば、「Unless otherwise stated,a collection must be live.」です.
getElementsByClassName
の戻り値がstaticであることが標準で示されていない以上、HTMLCollection
がliveである.WHATWG記述
getElementsByClassName
の実装は,まずパラメータからASCII空白文字でクラス名を分割し,得られたクラス名を1つの秩序ある集合を構成した後,集合内のすべてのクラス名に一致する要素を返す.quirks modeでない限り、大文字と小文字は敏感であり、Document
およびElement
に定義されている.互換性
WebKitコード解析
従来のいくつかの方法と同様に,
ContainerNode
で実現され,ClassNodeList
をNodeListsNodeData::addCacheWithAtomicName<>
のtemplate specializationとして用いた.前回commitはnodeMatches
をelementMatches
に変更しましたが、githubのmirrorではClassNodeList
はまだ変更されていないようです.ClassNodeList
のnodeMatches
フィルタ基準(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
は、クラス名の集合を維持するために SpaceSplitString
のm_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を分解するたびにパラメータtokenProcessor
のprocessToken
を呼び出す.SpaceSplitStringData::create (const AtomicString& keyString)
まずTokenCounter
をtokenProcessor
としてtokenizeSpaceSplitString
を呼び出し、クラス名文字列をまず統計token数をスキャンしてメモリの割り当てを容易にし、次にリロードされたSpaceSplitStringData::create(const AtomicString& keyString, unsigned tokenCount)
を呼び出し、TokenAtomicStringInitializer
をtokenProcessor
としてもう一度文字列をスキャンし、各tokenの内容を割り当てられたメモリに保存する.マッチングを判断するアルゴリズムは乱暴だ......WebCore/dom/SpaceSplitStringを参照.cppのcontainsAllとWebCore/dom/SpaceSplitString.hのcontainsでは、意外にも線形ルックアップセット線形ルックアップのO(mn)(mとnはそれぞれ検索するクラス名と検索される要素の実際のクラス名)であることがわかりますが...アプリケーションシーンでは一般的なクラス名が少なく、多点でも5、6個であることを考慮すると、検索されるクラス名はもっと少ないかもしれませんが、mnを乗じるとせいぜい2、30程度かもしれませんが、一般的には10を超えません.この場合、高度なデータ構造によるoverheadは、単純な線形検索よりも大きい可能性があるため、このように実現するのも合理的である.