First of all, I want to talk about the loading and execution of Javascript. Generally speaking, browsers have two major features for Javascript operation: 1) Execute immediately after loading, 2) It will block subsequent content of the page (including page rendering and other resources download) during execution. Therefore, if multiple js files are introduced, then for the browser, these js files are loaded serially and executed sequentially.
Because JavaScript may operate the DOM tree of HTML documents, browsers generally do not download css files in parallel like parallel downloads, because this is caused by the particularity of js files. So, if your javascript wants to operate the subsequent DOM element, basically, the browser will report an error saying that the object cannot be found. Because when Javascript is executed, the HTML behind is blocked, and there is no DOM node behind the DOM tree. So the program is reported as an error.
The traditional way
So, when you write the following code in the code:
The code copy is as follows:
<script type="text/javascript"
src="http://coolshell.cn/asyncjs/alert.js"></script>
Basically, the <script> tag in the head will block the loading of subsequent resources and the generation of the entire page. I have made a special example you can take a look at: Example 1. Note: There is only one sentence in my alert.js: alert("hello world"), which makes it easier for you to see how JavaScript blocks the things behind it.
So, you know why many websites put JavaScript at the end of the web page, either using events like window.onload or docmuemt ready.
In addition, because most Javascript code does not need to wait for pages, we load functions asynchronously. So how do we load asynchronously?
document.write method
So, you may think document.write() can solve the problem of not blocking. Of course you will think that after the document.write <script> tag can be executed, the following things can be executed, which is correct. This is true for Javascript code in the same script tag, but for the entire page, this will still block. Here is a test code:
The code copy is as follows:
<script type="text/javascript" language="javascript">
function loadjs(script_filename) {
document.write('<' + 'script language="javascript" type="text/javascript"');
document.write(' src="' + script_filename + '">');
document.write('<'+'/script'+'>');
alert("loadjs() exit...");
}
var script = 'http://coolshell.cn/asyncjs/alert.js';
loadjs(script);
alert("loadjs() finished!");
</script>
<script type="text/javascript" language="javascript">
alert("another block");
</script>
What do you think the order of alerts is? You can try it in different browsers. Here is the test page you want to close: Example 2.
Defer and async properties of script
IE has supported defer tags since IE6, such as:
The code copy is as follows:
<script defer type="text/javascript" src="./alert.js" >
</script>
For IE, this tag will allow IE to download js files in parallel and hold their execution until the entire DOM loading is completed (DOMContentLoaded). Multiple defer <script> will also run in the order they appear when executed. The most important thing is that after defer is added to <script>, it will not block the rendering of subsequent DOM. However, because this defer is only used for IE, it is generally used less.
Our standard HTML5 also adds an attribute that loads JavaScript asynchronously: async. No matter what value you assign to it, as long as it appears, it starts loading the js file asynchronously. However, async loading will have a serious problem, that is, it faithfully implements the "execute immediately after loading", so although it does not block the rendering of the page, you cannot control the order and timing of its execution. You can take a look at this example to experience it.
The browsers that support the async tag are: Firefox 3.6+, Chrome 8.0+, Safari 5.0+, IE 10+, Opera does not support it (from here), so this method is not very good either. Because not all browsers can do it.
Dynamically create DOM
This method is probably the most used.
The code copy is as follows:
function loadjs(script_filename) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', script_filename);
script.setAttribute('id', 'coolshell_script_id');
script_id = document.getElementById('coolshell_script_id');
if(script_id){
document.getElementsByTagName('head')[0].removeChild(script_id);
}
document.getElementsByTagName('head')[0].appendChild(script);
}
var script = 'http://coolshell.cn/asyncjs/alert.js';
loadjs(script);
This method has almost become a standard asynchronous way to load js files. For a demonstration of this method, please refer to: Example 3. This method also plays with JSONP things, that is, I can specify a background script (such as PHP) for script src, and this PHP returns a javascript function whose parameter is a json string, which returns to call our predefined javascript function. You can take a look at this example: t.js (This example is a small example of an asynchronous ajax call I collected on Weibo before)
Load js asynchronously on demand
The above example of the DOM method solves the problem of asynchronous loading of Javascript, but does not solve the problem that we want it to run at the time we specified. So, we just need to bind the above DOM method to a certain event.
for example:
Tied to window.load event - Example 4
You must compare the differences in execution between Example 4 and Example 3. In both examples, I specially used a JavaScript with code highlighting to see the execution of the script with code highlighting and the execution of my alert.js. You will know the difference)
The code copy is as follows:
window.load = loadjs("http://coolshell.cn/asyncjs/alert.js")
Tied to a specific event - Example 5
The code copy is as follows:
<p style="cursor: pointer" onclick="LoadJS()">Click to load alert.js </p>
This example is very simple. Only when you click on a DOM element will our alert.js be actually loaded.
More
However, binding to a specific event seems to pass a little bit, because the real download of js will only be done when clicking, which will be too slow again. Okay, here we have to throw our ultimate problem - we want to download the js file asynchronously to the user's local area, but not execute it, only if we want to execute it.
It would be great if we had the following method:
The code copy is as follows:
var script = document.createElement("script");
script.noexecute = true;
script.src = "alert.js";
document.body.appendChild(script);
//We can do this later
script.execute();
Unfortunately, this is just a beautiful dream. Today our Javascript is still relatively primitive, and this "JS dream" has not been realized yet.
Therefore, our programmers can only use hack to do it.
Some programmers use non-standard script type to cache javascript. like:
The code copy is as follows:
<script type=cache/script src="./alert.js"></script>
Because "cache/script", this thing cannot be parsed by the browser at all, so the browser cannot execute alert.js as javascript, but it has to download the js file, so it can be done. Unfortunately, webkit strictly follows the HTML standards - for such unrecognized things, they will directly delete them and do nothing. So, our dream was broken again.
So, we need to hack it a little more. Just like N played preload images many years ago, we can use the object tag (or iframe tag), so we have the following code:
The code copy is as follows:
function cachejs(script_filename){
var cache = document.createElement('object');
cache.data = script_filename;
cache.id = "coolshell_script_cache_id";
cache.width = 0;
cache.height = 0;
document.body.appendChild(cache);
}
Then, we call this function at the end. Please see the related example: Example 6
Press Ctrl+Shit+I under Chrome, switch to the network page, and you can see that alert.js has been downloaded but it has not been executed. Then we use the method of Example 5, because the browser side has cache, alert.js will no longer be downloaded from the server. Therefore, the execution speed can be guaranteed.
You should be familiar with this kind of preload. You can also use Ajax methods, such as:
The code copy is as follows:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'new.js');
xhr.send('');
I won’t say more and give examples here. You can try it yourself.
Finally, let’s mention two js, one is ControlJS and the other is HeadJS, which is specially used to make asynchronous load javascript files.
OK, this is all the content. I hope you can have an understanding of Javascript loading and execution, as well as related technologies after reading it. At the same time, I also hope that all the front-end experts will give you advice!