jQuery原理シリーズ-cssセレクタ実装

4937 ワード

jQueryの最も強力な機能はcssセレクタを通じて要素を探すことができることであり、そのソースコードの半分はsizzle cssセレクタエンジンのコードであり、html 5規範が出た後、documentを増加した.义齿querySelectorAllは直接要素を検索し,モバイル端末の開発を行う場合,jQueryを使用する必要性が大幅に低下する.
jsコードでcssセレクタを実現するには、必ず正規表現で文字列を識別する必要があります.もちろん、ブラウザが提供するオリジナルapiの効率はもっと高く、以下のコードは原理的な展示だけを行い、優先性能はありません.
 
たとえば
1)id検索は明らかにdocumentである.getElementByIdはより効率的で、ブラウザはすでにhashをしており、要素を一度に見つけて各ノードを遍歴する必要はありません.
2)nameを検索するにはdocumentを用いる.getElementsByNameの方が効率的で、ブラウザはすでにこのnameを含む集合を作っています.
3)タグ名を検索するにはdocument.getElementsByTagNameの方が効率的で、ブラウザはすでにこのtagを含む集合を作っています.この集合からサブセットを検索すると、明らかに多くの要素を遍歴することが少なくなります.ブラウザが要素の作成時にキャッシュの集合を更新したかどうかは分かりません.しかし,この集合からターゲット要素のサブノードがcontainsでも性能損失があるかどうかを判断する.
 
では、原生apiでセレクタを最適化する問題を考慮せずに、純粋な正規表現だけで簡単な実装を行い、まず正規判断で#が含まれている場合はidセレクタ、点番号が含まれている場合はclassセレクタ、[]が属性セレクタである場合は、ターゲットを検索してからサブノードを巡り始め、childNodesサブノードのidを再帰関数で巡り、name,className,getAttributeが一致するかどうかは,一致するとその要素を返す.完全なコードは次のとおりです.
 
html:
<body>
    <div>
        
        <span id="sp_id">hello,id</span>
        <span class="sp_class">hello,class</span>
         <span name="sp_name" >hello,name</span>
         <b>hello,tag</b>
    </div>
 </body>

javascript:
<script type="text/javascript">
     
     
     function find(el, selector) { //     ,    jquery find  ,   id,class,attr   ,             
        var m = selector.match(/([#\.\[])([\w\W]+)/i);
        var type, key,attrName, result;
        if (m) {
            if (m[1] == ".") {
                type = "class"; key = m[2];
            } else if (m[1] == "#") {
                type = "id"; key = m[2];
            } if (m[1] == "[") {
                type = "attr";
                m = m[2].match(/(\w+)=(\w+)/i);
                attrName = m[1];
                key = m[2];
            }
        } else {
            type = "tag"; key = selector;
        }
        
        function findChild(node) {
            var c;
            for (var i = 0; i < node.childNodes.length; i++) {
                c = node.childNodes[i];
                if (type == "class" && c.className == key) {
                    result = c;
                    return;
                } else if (type == "id" && c.id == key) {
                    result = c;
                    return;
                } else if (type == "attr" &&  c.getAttribute && c.getAttribute(attrName) == key) {
                    result = c;
                    return;
                } else if (type == "tag" && c.tagName && c.tagName.toLowerCase() == key) {
                    result = c;
                    return;
                }
                findChild(c);
            }
        }
        findChild(el);
        return result;
        
    }
    
    console.log(find(document.body,"#sp_id").innerHTML);
    console.log(find(document.body,".sp_class").innerHTML);
    console.log(find(document.body,"[name=sp_name]").innerHTML);
    console.log(find(document.body,"b").innerHTML);
        
    </script>