6

In most tutorials, there are two ways mentioned about how to execute a jquery script:

  • with window.onload hook.
  • with a $(document).ready(function(){...}) event (and could be abbreviated to $(function(){...}))

And I found that it even works when I omit all them, just place the code in a <script></script> occlusion could achieve the same purpose. Just like this:

<html>
<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
<body>
    <button id="btn" name="test" value="clickme">clickme</button>
</body>
<script>

//$(document).ready( function(){
//    $('#btn').on("click", function(e){
//        alert("hi")
//     }
//)})

$('#btn').on('click', function(e){
    alert('hi')
})
</script>
</html>

As you can see both the un-commented code (which omit all the document.ready staff or a window.onload) and the commented code can give me a alert as expected.

So my question is, in such cases(binding events), since I can write code more elegant as the un-commented snippet. Why should I bother to write the code as in most tutorials told (which is as the commented style above) ?

armnotstrong
  • 8,605
  • 16
  • 65
  • 130
  • 1
    only works without if the code comes after the elements that the code references...so they exist at the time the code runs. – charlietfl Mar 09 '15 at 03:43

4 Answers4

7

<script> tags in your HTML that do not have the defer or async attributes will execute in the order the HTML document is parsed from top down. That means that a script near the top of the document will execute before the rest of the document has been parsed and thus before it is available. This makes the placement of a script or the execution timing of a script relevant in many cases.

In controlling this execution timing, you have at least five choices for executing startup scripts:

  1. You can put the script in the <head> section or the top of the <body> section and execute it as it loads. This has the disadvantage that the DOM is not yet loaded so you can't operate on elements within the page.

  2. You can insert the script right before the </body> tag and all of the DOM will be loaded and your script will be able to access everything.

  3. You can insert your script anywhere you want (including in the <head> tag) and use $(document).ready(fn) to not execute the fn until the DOM is ready. Internally, jQuery listens for the DOMContentLoaded event and when it fires, it executes any .ready() handlers.

  4. You can insert your script anywhere you want (including in the <head> tag) and use window.onload(fn) to not execute the fn until the DOM is ready and all external resources such as images have loaded. Note, you can also use the jQuery version $(window).load(fn).

  5. You can use the async or defer attributes on the script tag to force it to load asynchronously and somewhat later. This will create an indeterminate time of script execution (though always later than if it was just inline) so you will likely need some specific control like $(document).ready() to know that the DOM is safe before your script executes. You can see these other questions/answers Script Tag - async & defer and Load and Execute order of scripts for a lot more details on the operation of the async and defer attributes.

So, if you carefully place your script tag in the right place or your startup script does not try to access DOM elements, you don't need to use either $(document).ready(fn) or window.onload(fn).

But, if you don't entirely control where the script is placed and you need to access DOM elements or you want your script to be able to be placed anywhere and still have it do the right thing or if you just want all your scripts in the <head> tag, then you will need to delay the execution of your script until the DOM is ready and either $(document).ready(fn) or window.onload(fn) will make it easy to do so.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

Well the two aren't quite the same. Inline Javascript is executed as soon as it is encountered as the DOM is parsed top-down. However, the hooks you've mentioned are executed after the DOM is loaded/ready. So yea, apart from organization, if you are certain your JS only depends on parts of the DOM that are loaded prior to the inlining - you are fine. Otherwise you definitely need the hook.

pragmatist1
  • 919
  • 6
  • 16
0

According to jQuery documentation:

.ready( handler )

Description: Specify a function to execute when the DOM is fully loaded.

document.ready means the browser has parsed all DOM elements. There is a case if you have a long <body> tag with lots of elements, the DOM Element objects are not fully created by the browser, and it also started to parse your JavaScript. At that very moment you will not be able query the #btn element from your DOM tree, thus the event listener cannot be attached to the element.

Community
  • 1
  • 1
steve
  • 1
  • 1
0

To answer you question, the reason you're not finding any difference between adding and omitting $(document).ready(function(){}); is because you've kept it just before the end of html tag.

  • Your code is parsed from top to bottom.
  • By the time it reaches your script, the DOM is ready. Hence $(document).ready will fire.
  • But since the script is at the bottom, you're sure the DOM is ready. In this case, $(document).ready makes no difference.

To see the difference, move your script tag to the top <head> section. Then to make sure your script workes properly, you need to include it between $(document).ready. Else you'll be adding click handler to a non-existing button, which won't work.

As for the difference between window.onload and $(document).ready:

  1. window.onload is fired after everything is loaded. This means when it is fired, the DOM is ready and so is all the images and other resources are ready.

  2. On the other hand $(document).ready is fired after the DOM is loaded. This is before all the images and other resources are downloaded and ready. Hence this ensures your script will work and also it'll be triggered faster than using window.onload.

window.onload documentation

$(document).ready documentation

Rison
  • 111
  • 6