为什么`.getElementById`在节点上不起作用? [英] Why doesn't `.getElementById` work on a node?

查看:59
本文介绍了为什么`.getElementById`在节点上不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想,如果 .getElementById 在所有节点上都可用,那么将有两个主要优点:

  1. 可以选择不属于文档的节点.

    例如,我想做类似的事情

      function foo(html){var el = document.createElement('div');el.innerHTML = html;var target = el.getElementById('target');/*使用`target`做某事*/} 

    但是我不能,因为我得到了 TypeError:el.getElementById不是一个函数.

    然后,我不想使用类而不是ID,我必须这样做

      function foo(html){var el = document.createElement('div');el.innerHTML = html;document.body.appendChild(el);var target = document.getElementById('target');document.body.removeChild(el);/*使用`target`做某事*/} 

    但是文档可能已经具有一个带有 id ="target" 的元素.那我应该做

      function foo(html){var iframe = document.createElement('iframe');iframe.onload = function(){var doc = iframe.contentDocument ||iframe.contentWindow.document,el = document.createElement('div');el.innerHTML = html;doc.body.appendChild(el);var target = doc.getElementById('target');document.body.removeChild(iframe);/*使用`target`做某事*/};iframe.src ='about:blank';document.body.appendChild(iframe);} 

    但是,如果我想让 foo 返回与 html 相关的内容,则上面的代码将不起作用,因为主要代码将在 onload <之后运行/code>事件.

  2. 如果文档中包含很多元素,并且您知道所搜索的元素是变量中已有元素的后代,则可以提高性能

    例如,如果我有一个具有以下结构的文档:

     < body>< div id ="div-1">< div id ="div-1-1">< div id ="div-1-1-1">...</div>< div id ="div-1-1-2">...</div>...</div>< div id ="div-1-2">< div id ="div-1-2-1">...</div>< div id ="div-1-2-2">...</div>...</div>...</div>< div id ="div-2">< div id ="div-2-1">< div id ="div-2-1-1">...</div>< div id ="div-2-1-2">...</div>...</div>< div id ="div-2-2">< div id ="div-2-2-1">...</div>< div id ="div-2-2-2">...</div>...</div>...</div>...</body> 

    我愿意...

      var el1 = document.getElementById('div-9999999'),el2 = document.getElementById('div-9999999-1-2'),el3 = document.getElementById('div-9999999-1-2--2-999999'),el4 = document.getElementById('div-9999999-1-2-999999-1-2-3-4-5'); 

    ...可能比

    慢得多

      var el1 = document.getElementById('div-9999999'),el2 = el1.getElementById('div-9999999-1-2'),el3 = el2.getElementById('div-9999999-1-2-999999'),el4 = el3.getElementById('div-9999999-1-2-999999-1-2-3-4-5'); 

    (当然,此示例是一个简化,在这种情况下,使用 .childNodes [] .children [] 会更好);

然后,为什么 .getElementById 在节点上不起作用?我看不到任何缺点,只有优点

解决方案

主要原因是效率.

在文档级别,需要维护一个ID参考表,并且对文档的任何更改都需要 O(1) 对该表的修改.为了在节点级别实现它,需要为每个节点维护一个等效表,并更新任何给定元素,无论它是否附加到文档中,都需要遍历每个元素其父节点.这样很快就会消耗大量内存,并且需要很长时间才能更新DOM.

要注意的另一重要事项是(至少从Java脚本的角度来看)每个元素归文档(或文档片段)所有.因此,但只要有一个ID附加到文档中,我就可以有重复的ID"这样的说法实际上并没有堆叠-仅 可以根据节点上的节点进行管理考虑到DOM.

I thing that if .getElementById were available on all nodes, there would be two main advantages:

  1. It could be possible to select nodes which don't belong to the document.

    For example, I would like to do something like

    function foo(html){
        var el = document.createElement('div');
        el.innerHTML = html;
        var target = el.getElementById('target');
        /* Do something with `target` */
    }
    

    But I can't because I get TypeError: el.getElementById is not a function.

    Then, I don't want to use a class instead of an id, I must do

    function foo(html){
        var el = document.createElement('div');
        el.innerHTML = html;
        document.body.appendChild(el);
        var target = document.getElementById('target');
        document.body.removeChild(el);
        /* Do something with `target` */
    }
    

    But the document could already have an element with id="target". Then, I should do

    function foo(html){
        var iframe = document.createElement('iframe');
        iframe.onload = function(){
            var doc = iframe.contentDocument || iframe.contentWindow.document,
                el = document.createElement('div');
            el.innerHTML = html;
            doc.body.appendChild(el);
            var target = doc.getElementById('target');
            document.body.removeChild(iframe);
            /* Do something with `target` */
        };
        iframe.src = 'about:blank';
        document.body.appendChild(iframe);
    }
    

    But the code above doesn't work if I want foo to return something related with html, because the main code runs after, with the onload event.

  2. It could increase the performance, if the document has lots of elements and you know that the element you are searching is a descendant of an element that you already have in a variable

    For example, if I have a document with the following structure:

    <body>
    <div id="div-1">
      <div id="div-1-1">
        <div id="div-1-1-1">
          ...
        </div>
        <div id="div-1-1-2">
          ...
        </div>
        ...
      </div>
      <div id="div-1-2">
        <div id="div-1-2-1">
      ...
        </div>
        <div id="div-1-2-2">
          ...
        </div>
          ...
      </div>
      ...
    </div>
    <div id="div-2">
      <div id="div-2-1">
        <div id="div-2-1-1">
          ...
        </div>
        <div id="div-2-1-2">
          ...
        </div>
         ...
      </div>
      <div id="div-2-2">
        <div id="div-2-2-1">
          ...
        </div>
        <div id="div-2-2-2">
          ...
        </div>
         ...
      </div>
      ...
    </div>
    ...
    </body>
    

    And I do...

    var el1 = document.getElementById('div-9999999'),
        el2 = document.getElementById('div-9999999-1-2'),
        el3 = document.getElementById('div-9999999-1-2-999999'),
        el4 = document.getElementById('div-9999999-1-2-999999-1-2-3-4-5');
    

    ... it could be much slower than

    var el1 = document.getElementById('div-9999999'),
        el2 = el1.getElementById('div-9999999-1-2'),
        el3 = el2.getElementById('div-9999999-1-2-999999'),
        el4 = el3.getElementById('div-9999999-1-2-999999-1-2-3-4-5');
    

    (Of course, this example is a simplification, and in this case using .childNodes[] or .children[] would be much better);

Then, why doesn't .getElementById work on a node? I don't see any disadvantage, only advantages

解决方案

The primary reason is efficiency.

At the document level, a single ID reference table needs to be maintained, and any alterations to the document require an O(1) modification to this table. To implement it at the node level, an equivalent table would need to be maintained for each node and updates to any given element, regardless of whether it is attached to the document, would need to bubble through every one of its parent nodes. This very quickly eats a lot of memory and takes a long time to update the DOM.

Another important thing to note is that (from a Javascript point of view, at least) every element is owned by a document (or document fragment). Therefore the argument of "but I can have duplicated IDs as long as only one of them is attached to the document" doesn't really stack up - it's only possible to manage this based on the nodes on the DOM when you take this into account.

这篇关于为什么`.getElementById`在节点上不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆