5

This is my HTML Code

<html> 
  <head>
     <title> Test Page </title>
     <script type='text/javascript'>
        function test() {
           var ta = document.getElementsByTagName('body')[0].getElementsByTagName('li');
        }
     </script>
  </head>
  <body onload='test()'>
     <ul>
        <li> Test 1 </li>
        <li> Test 1 </li>
        <li> Test 1 </li>
        <li> Test 1 </li>
     </ul>
  </body>
</html>

Which of the following is better and why?

document.getElementsByTagName('body')[0].getElementsByTagName('li')

document.getElementsByTagName('li')

Also I couldn't find any documentation or reference for getElementsByTagName implementation across browsers [atleast a overview on some major browsers] although I found really interesting things about document.getElementById that it is kind of hash look up atleast in firefox and chrome. Wish to have some help on the implementation too.

Tamil
  • 5,260
  • 9
  • 40
  • 61

4 Answers4

8

First of all, you should never get the body tag with this:

document.getElementsByTagName('body')[0]

It's always more efficient to just use the built-in property for the body:

document.body

Second of all, all performance questions should be answered by testing with a tool like jsPerf. In this case, you can build a test that compares between these two if you want, but I think the point is moot given the previous simplification:

document.getElementsByTagName("li")

and

document.body.getElementsByTagName("li")

In a jsPerf I built to test this, document.getElementsByTagName('li') is the fastest, followed by document.body.getElementsByTagName('li') and document.getElementsByTagName('body')[0].getElementsByTagName('li') is the slowest.

Here's a screenshot of the test from several browsers:

enter image description here

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks for response. I accept jsperf would really give me the better one of these two. But I wanna know the reason. I mean, I wish to know how does getElementsByTagName work – Tamil Feb 11 '12 at 16:43
  • 1
    The difference between these scenarios has nothing to do with how `getElementsByTagName()` works. Internally, all three are going to be using exactly the same method. The difference is entirely in how you direct it to search the entire document body (e.g. what comes before the call to `getElementsByTagName()`. – jfriend00 Feb 11 '12 at 16:51
  • So you mean that getElementsByTagName is going to traverse the dom entirely rather than following some optimizations as getElementsById? I felt this to be an optimization coz 3rd one narrows down the search to body tag only rather the entire dom and browser might optimize the search for body tag. Wish to have your suggestion. – Tamil Feb 12 '12 at 12:39
  • @Tamil - the ONLY other place there could be tags are in the `` section. So, if you ran a test case on a document with a ton of stuff in the `` section, maybe it would be faster to search only the ``, but that depends upon the internal implementation. If you really want to know, design your own test case and measure it. In most real world situations, you wouldn't be doing `getElementsByTagName()` on the entire body - you would get some particular parent object and then just do `getElementsByTagName()` on that parent. – jfriend00 Feb 12 '12 at 15:42
  • Ya actually that is my use case. Here I have mentioned body for an example. And what you are saying makes sense. I'll try my own test case on jsperf. So reaching a particular parent using getElementById and then getElementsByTagName would make sense I hope. – Tamil Feb 13 '12 at 05:15
4

First off, you should avoid functions inside functions to improve performance and on top of that DOM is slow.

You can refactor your code like this:

function getLis(){
  return document.getElementsByTagName('li');
}

function test() {
  var ta = getLis();
}

This way, javascript only stores these two functions in memory once and you call call them as many times as you want.

For your question, later should be faster because it has one call less:

document.getElementsByTagName('li')

As for speed, my guess was correct, I have created test case at jsperf:

Speed Test

Results:

document.getElementsByTagName('li')

2,141,067
±2.07%
fastest

document.getElementsByTagName('body')[0].getElementsByTagName('li')

704,856
±4.40%
67% slower

And Screenshot:

enter image description here

Community
  • 1
  • 1
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
0

Both lines of code are essentially the same thing, except document.getElementsByTagName('li') will search from the top level of the document which is the , but as @jfriend00 pointed out you should reference the body tag as document.body.

Using document.getElementsByTagName with .getElementById will be much more efficient in larger DOM structures. For instance if you had an id of #my-list on the ul you could

var mylist = document.getElementById('#my-list');
var lis = mylist.getElementsByTagName('lil);

Modern browsers have better methods for searching the DOM such as querySelectorAll, check this resource https://developer.mozilla.org/en/DOM/Document.querySelectorAll

Troy Watt
  • 868
  • 8
  • 16
0

Despite the last test gave me an error, you can check that here: http://jsperf.com/document-body-id

I made some tests with 200k interactions. The results told me that document.get... is as fast as the saved body version (31ms); the document.body.get... version was the slowest (52ms). So, use document directly :D