Let's say I put Javascript in the head, and say the script tries to
get some HTML element by ID, and register a click handler for it. Now
since, the HTML has not been loaded yet (because the script is called
in head), will this work?
No, this won't work. Whenever <script>
tag is seen, javascript is executed right away before going further with DOM building. (if javascript is external, it will wait to fetch it over network and execute it) It will act upon the current snapshot of DOM if the javascript is using DOM APIs like getElementById
. When script tries to get the element by id, it tries to get it from DOM, (All DOM APIs acts on DOM) which is being built right now. As the element is not yet added to DOM (we are processing head) it won't be able to get the element. As it cannot get the element it will throw error if you try to access addEventListener
or onclick
of null
.
On the other hand, if register a function in head which gets called
when DOM is loaded, and inside that function I put code which
registers handler for click on some button, then as I understand user
has chance to click button but the handler will not be called because
the whole DOM was not loaded yet (and that is where the button click
handler is registered). Am I correct?
Yes, you are correct. DOM load generalises the condition that all elements are added to the DOM and is ready for any operation on any element defined by HTML.
Also, window.load
will be triggered only after DOM is loaded and all the external resources like images, videos are also loaded. Using it can delay the event attachments further.
What if I want to add event listener immediately?
If you want to immediately bind an event you can do it with inline scripts, just after the element although usually not a requirement and neither a good practice.
<p>whatever</p>
<button id="mybutton">Click me</button>
<script>
document.getElementById('mybutton').addEventListener(...
</script>
<p>rest of HTML</p>
This also opens another possibility, if you put your scripts at the end of HTML instead of head, it makes sure that all elements are added to the DOM and DOM is practically ready for any operations using DOM APIs. This was used widely when listening to DOM load event was not that easy. Although I can't find the correct reference, this was a recommendation by Doug Crockford.