0

I have simple page that needs very small JS functionality. When i use <script> tag, i get different behaviour on different browsers, depending on where the <script> tag is placed.

On Chrome(65) and Firefox(59) the position of the <script> tag dose not matter and the code is executed before the page is rendered. lets say that i have <h1> and before it I have <script> that uses that <h1> DOM node. It works. Even if i move the <script> to the <head> of the page, it still works.

now if i try the same thing in Edge or IE11 i see what i think is the logical thing, and that is that JavaScript can not see the element if the <script> is before the <h1>.

My question is why we have such different behaviour, isn't this part of a specification? And witch of the bot is the proper way the code should work?

  • *"the position of the ` – Felix Kling Apr 26 '18 at 22:30
  • 1
    Related: [Why does jQuery or a DOM method such as getElementById not find the element?](https://stackoverflow.com/q/14028959/218196) – Felix Kling Apr 26 '18 at 22:31
  • A general rule of thumb is to put your script just above the closing

    tag so that all your DOM would have rendered. It's a safeguard against issues like you mentioned. The exception are those scripts where things must init before DOM (e.g. AB tests, GA, etc.)

    – bigbitecode Apr 26 '18 at 22:32
  • *lets say that i have `

    ` and before it I have `

    – Scott Marcus Apr 26 '18 at 22:35
  • @FelixKling The oddest thing is that with getElementsByTagName works with getElementById dose not. – Nikola.grancharov Apr 26 '18 at 22:35
  • 1
    @Nikola.grancharov: *How* are you using it? `getElementsByTagName` returns a live list, so it will update itself once the element becomes available. However, that should also be the case in IE I guess. You can see here that the list returned by `getElementsByTagName` is empty: https://jsfiddle.net/chow4to2/ – Felix Kling Apr 26 '18 at 22:37
  • 1
    If you would just show us the code you are working with, this would be a lot simpler. – Scott Marcus Apr 26 '18 at 22:43
  • the code is literally what Felix Kling put in the jsfiddle: https://jsfiddle.net/3sfp4gqw/ @FelixKling what you say about the live list makes som much sense. Still in IE11 and Edge i get – Nikola.grancharov Apr 26 '18 at 22:46
  • 1
    Are you actually using `console.log` to verify the value? If yes, then the reason might be that Firefox and Chrome show the current "content" of the value when you expand it. I don't know about IE. Log the `.length` property instead, it should be `0` in all cases. – Felix Kling Apr 26 '18 at 22:49

2 Answers2

1

.getElementsByTagName() (along with .getElementsByName() and .getElementsByClassName()) return "live" node lists. These are collections that will always reflect the current state of the DOM, so even if an element gets added or removed after you've declared your collection variable, you will get the most up to date collection. It works because every time you access your variable that references the "live" collection, the DOM is re-scanned. This is great to give you up-to-date results, but not great for performance. So, if your document doesn't dynamically change very much, you are better off not using these methods and instead use .querySelectorAll(), which returns a static node list (one who's content is established at the time of the method call and not updated even if DOM changes occur later) or simply .getElementById() if you are looking for a single element that has an id or .querySelector() if you are looking for only the first element that matches a CSS selector.

Now, here's the important part, no matter what method you use to get any kind of node list (live or static), you will always get a list object back, even if that list is empty.

What you are experiencing across browsers is just the difference in how they report the object itself to you. However, if you were to access some specific aspect of the object or any members of the object, all browsers would give you the same results and if you are querying prior to the element(s) being parsed, you will have a node list with 0 items in it. This is why it's a best-practice to place your scripts that need access to DOM elements just before the closing body tag (</body>), because by that time, all the HTML has been parsed and you will definitely be able to find all elements.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

As Felix Kling found, i was using document.getElementsByTagName() with returns live list. Combined that with the fact that I was verifying the result with console.log() that in Chrome and Firefox gets the value of the list when I clicked the expand button, therefore I see my element. In IE and Edge, what is printed in the console is directly displayed with the current value of the live list, that had no elements at that time.

10x a lot for the quick response to everybody :)