簡體   English   中英

在javascript中實現document.getElementById

[英]Implementing document.getElementById in javascript

我正在嘗試在javascript中實現原生document.getElementById 我在javascript中實現了document.getElementsByClassName

 function getElementsByClassName (className) { var nodeList = []; function test(node) { if (node.classList && node.classList.contains(className)) { nodeList.push(node); } for (var index = 0; index < node.childNodes.length; index++) { test(node.childNodes[index]); } return nodeList; } test(document.body); return nodeList; }; // Fails here. function getElementById(className) { const result = []; function getEachIDNode(node) { if(node.contains(className)) { return node; } for(let i=0; i<node.childNodes.length; i++) { getEachIDNode(node.childNodes[i]); } } getEachIDNode(document.body); } console.log(getElementsByClassName('winner')); console.log(getElementById('test')); 
  <table> <tr id="test"> <td>#</td> <td class="winner">aa</td> <td>bb</td> <td>cc</td> <td>dd</td> </tr> </table> <table> <tr> <td>#</td> <td class="winner">aa</td> <td>bb</td> <td>cc</td> <td>dd</td> </tr> </table> <table> <tr> <td>#</td> <td class="winner">dd</td> <td>cc</td> <td>bb</td> <td>aa</td> </tr> </table> 

我試圖了解如何檢查節點是否具有屬性ID。

有人可以開導我嗎?

根據傳遞的參數檢查節點的id屬性(最好使用id作為參數而不是className ):

 function getElementById(id) { const result = []; function getEachIDNode(node) { if(node.id === id) { result.push(node); } for(let i=0; i<node.childNodes.length; i++) { getEachIDNode(node.childNodes[i]); } } getEachIDNode(document.body); return result; } console.log(getElementById('subchild')[0].innerHTML); 
 <div id="parent"> <div id="child1"> </div> <div id="child2"> <div id="subchild"> subchild! </div> </div> </div> 

但是如果你真的想要復制getElementById ,不要嘗試返回一個數組,返回一個元素:

 function getElementById(id) { let match = null; const doFind = node => { if (!match && node.id === id) match = node; if (!match) return [...node.childNodes].find(doFind); } doFind(document.body); return match; } console.log(getElementById('subchild').innerHTML); 
 <div id="parent"> <div id="child1"> </div> <div id="child2"> <div id="subchild"> subchild! </div> </div> </div> 

檢查DOM元素的屬性屬性。

function getElementById(id) {
    const result = [];

    function getEachIDNode(node) {
        if(!(node instanceof HTMLElement))
            return;

        if(node.hasAttribute('id') && node.getAttribute('id') === id) {
            result.push(node);
        }

        for(let i=0; i<node.childNodes.length; i++) {
            if(result.length > 0)
                return;
            getEachIDNode(node.childNodes[i]);
        }

    }
    getEachIDNode(document.body);
    return result[0];
}

本機document.getElementById不會遍歷搜索Element的DOM樹,這就是為什么它比其他DOM選擇方法更快的原因。

實際上,瀏覽器必須在活動文檔中保留一種帶有id的所有Elements的哈希映射。 所以他們只是對這個哈希映射 (不是一個)執行查找,如果找到它就返回該元素。

感謝IE </ irony>,他們確實將這個哈希映射的一些條目公開為全局window對象的屬性。

因此,如果您要進行自己的實現,可以先檢查此屬性是否返回Element。
不幸的是,可能會發生Element的id與window對象的其他屬性一致。 所以我們仍然需要走DOM。
在這種情況下,使用TreeWalker ,它是我們必須遍歷DOM樹的最快的API,而且當我們只對某種類型的節點(這里是Elements)感興趣時。

總而言之,更好的實現可能如下所示:

 function getElementById(id) { if (!(id in window)) { console.log(id, 'not found'); return null; // we are sure it's not set } // id maps are not marked as 'own property' if (!window.hasOwnProperty(id)) { if (window[id] instanceof Element && window[id].id === id) { // it's our Element console.log(id, 'found in window'); return window[id]; } // in case of duplicate window[id] should return an HTMLCollection // (IIRC only Chrome does it correctly though) if (window[id] instanceof HTMLCollection && window[id][0].id === id) { console.log(id, 'duplicate id is bad'); return window[id][0]; } } console.log(id, 'walking...'); var walker = document.createTreeWalker( document.documentElement, NodeFilter.SHOW_ELEMENT, null, false ); while (walker.nextNode()) { if (walker.currentNode.id === id) { return walker.currentNode; } } return null; } console.log(getElementById('foo')); console.log(getElementById('unique')); console.log(getElementById('duplicate')); window.overwritten = 'oups'; console.log(getElementById('overwritten')); 
 <div id="unique"> <div id="duplicate"></div> <div id="duplicate"></div> <div id="overwritten"></div> </div> 

正如您所看到的,在此實現中,只有在窗口的屬性已設置為其他值時才會遍歷DOM,從而大大提高了性能。

檢查節點是否具有屬性ID。您必須這樣寫:

            var attr_check = $(".selector").attr('id')                              
            if(attr_check != undefined || attr_check != false)
            {
                console.log("this element has attribute id")
            }

你也寫這個代碼:

           var attr_check = document.getElementById('div-id').attr('id')    

而不是這個:

           var attr_check = $(".selector").attr('id')   

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM