1

Please help me by answering with a short theory behind how it works as I would like to understand the logic rather than just get an answer. If you know of any material that explains it for beginners then please reference it. I have spent quite a lot of time researching and have come up blank and find the name or anything that explains this behavior.

My question is and want to understand, I thought the way browsers parse the html is line by line. When it encounters a <script> tag everything else comes to a halt (this basic example) whilst it passes it off to the js interpreter to also complete line by line. Once it has finished it then passes it back to the html parser to continue with the rest of the page

So my question is from the short example below, why is "find" being loaded before backup.js has completed, when I remove backup.js and have jQuery instead the code in console.log(find); works as expected, but when jQuery is removed from html and asked to be added via backup.js, which is still the first tag encountered before the console.log(find); at the bottom, it does not work? I get the following error message:

ReferenceError: $ is not defined
var find = $('.link');

Makes me believe that var find = $('.link'); is being attempted to be accessed before backup.js and jQuery have finished loading, but why is this when "find" comes long after backup.js? Or am I doing something wrong with the Javascript code in backup.js that adds it after rather than earlier?

I have this short piece of html:

<html>
    <head>

        <!--<script src="https://code.jquery.com/jquery-1.11.1.js"></script>-->
        <script type="text/javascript" src="backup.js"></script>        

        <meta charset="UTF-8">
        <title>My Web Page</title>
    </head>
    <body>
        <p>hello</p>    
        <div class="link">test</div>

    <script>
        var find = $('.link');
        console.log(find);
    </script>


    </body>
</html>

In backup.js I have this:

if(typeof jQuery=='undefined') {
   var head= document.getElementsByTagName('head')[0];
   var script= document.createElement('script');
   script.type= 'text/javascript';
   script.src= 'https://code.jquery.com/jquery-1.11.1.js';
   head.appendChild(script);
   console.log('jquery not found');
}
else{
    console.log('jquery found');
}
3
  • 1
    very descriptive title you got there bud Commented Nov 20, 2014 at 12:12
  • If I knew the name of the function or the behaiviour I would have added it. Hence I have explained as much as I can in the description so I can find out what the behaiviour it is called and how it works. Sorry if it wasn't descriptive enough, I just didn't know what you call it Commented Nov 20, 2014 at 12:14
  • The problem is simple. Loading the resource from the remote server takes time and is done in async to allow the rest of the code to keep going. This means that even though jQuery is loaded eventually, the rest of your script will hit an error long before that. Commented Nov 20, 2014 at 12:19

1 Answer 1

1

In your backup.js file you load jquery from the server if it does not yet exist. Loading something from the server through an Asynchronous call means it won't stop the page rendering, so what happens is:

The page starts rendering, it comes to backup.js, starts loading jquery from the server, keeps rendering the page while loading jquery, goes all the way to the bottom and then finds $(".link");. In this line of code the symbol "$" means jQuery (I want to use jquery for this part of code), but it might happen that jquery is not yet completely loaded, and so the program breaks and tells you ReferenceError: $ is not defined (or in human: you're trying to use $ but it doesn't exist).

To fix this, you can create a function that gets called when jquery has loaded:

if(typeof jQuery=='undefined') {
    var head= document.getElementsByTagName('head')[0];
    var script= document.createElement('script');
    script.type= 'text/javascript';
    script.src= 'https://code.jquery.com/jquery-1.11.1.js';
    script.onload = function() {
         runAfterjQueryLoad();
    }
    head.appendChild(script);
    console.log('jquery not found');
} else {
    console.log('jquery found');
}

function runAfterjQueryLoad() {
    var find = $('.link');
    console.log(find);
}

Working fiddle: http://jsfiddle.net/aj803z7u/

You're right about the page rendering top-down, but always be careful for asynchronous calls (also know as ajax, in case you want to search for more information on the web). The best way of learning is by doing. Think of a page you want to create and try to do it, searching for tutorials for each single small step (you can always come here on SO and ask questions) .

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks friend, this is exactly the type of theory I was looking for so helps me understand, I had a feeling that's what it was doing, but didn't know what is was called nor realise by default javascript was doing it asynchronously, I thought it was doing the opposite. Is this a default behaiviour? Now I know it's called async, I'm going try search up some knowledge about it, but if you know of any good site or resource to read up on if you can point me in the right direction. Thanks
Yes, loading something from the server through javascript using asynchronous calls is default behavior. You can even load entire new html section through ajax (think of facebook posts that get loaded when you scroll down). You could take a look at 30 days to learn jquery code.tutsplus.com/courses/30-days-to-learn-jquery . I don't know about this particular course but I know this 30 days thing are well done. Other then that, just try things out. I did it on my own and now I work as a front end developer. Just keep going.
Thanks but I just noticed by trying Arvind's code, it is still producing the $ not referenced error. How would you stop everything else loading so that "find" works?
I edited my answer to provide a working solution. Just place the function part in your last script and you should be good to go

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.