简体   繁体   English

在javascript中实现document.getElementById

[英]Implementing document.getElementById in javascript

I'm trying to implement native document.getElementById in javascript. 我正在尝试在javascript中实现原生document.getElementById I've implemented document.getElementsByClassName in javascript. 我在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> 

I'm trying to understand how I can check if a node has an attribute ID. 我试图了解如何检查节点是否具有属性ID。

Can someone enlighten me? 有人可以开导我吗?

Check the id property of the node against the passed argument (probably better to use id as an argument rather than className ): 根据传递的参数检查节点的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> 

But if you actually want to replicate getElementById , don't try to return an array, return a single element : 但是如果你真的想要复制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> 

Check attribute property of DOM element. 检查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];
}

The native document.getElementById does not walk through the DOM tree searching for your Element, and that's why it is faster than other DOM selection methods. 本机document.getElementById不会遍历搜索Element的DOM树,这就是为什么它比其他DOM选择方法更快的原因。

Indeed, browsers have to keep a kind of a hash-map of all the Elements with an id in the active Document. 实际上,浏览器必须在活动文档中保留一种带有id的所有Elements的哈希映射。 So they just perform a look-up over this hash-map (which is not one) and return the element if they found it. 所以他们只是对这个哈希映射 (不是一个)执行查找,如果找到它就返回该元素。

Thanks to IE </irony>, they do expose some of the entries of this hash-map as properties of the global window object. 感谢IE </ irony>,他们确实将这个哈希映射的一些条目公开为全局window对象的属性。

So if you are going to make your own implementation, you can first check if this property returns your Element. 因此,如果您要进行自己的实现,可以先检查此属性是否返回Element。
Unfortunately, it may happen that an Element's id do concur with an other property of the window object. 不幸的是,可能会发生Element的id与window对象的其他属性一致。 So it may happen that we still need to walk the DOM. 所以我们仍然需要走DOM。
In this case, use a TreeWalker , which is about the fastest API we have to walk through a DOM tree, moreover when we are only interested in some type of nodes (here Elements). 在这种情况下,使用TreeWalker ,它是我们必须遍历DOM树的最快的API,而且当我们只对某种类型的节点(这里是Elements)感兴趣时。

So all in all, a better implementation could look like this: 总而言之,更好的实现可能如下所示:

 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> 

As you can see, in this implementation we walk the DOM only if the window's property has been set to an other value, greatly improving the performances. 正如您所看到的,在此实现中,只有在窗口的属性已设置为其他值时才会遍历DOM,从而大大提高了性能。

To check if a node has an attribute ID.You have to write like this: 检查节点是否具有属性ID。您必须这样写:

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

You also write this code: 你也写这个代码:

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

instead of this: 而不是这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM