When we load and execute JavaScript in a webpage, there are many points we need to care about because of its design and feature. There are two features about JavaScript execution in a browser: 1). The JavaScript codes will be executed immediately once loaded;2). When JavaScript codes are being executed, they will block the following contents (including page rendering and other resources downloading). So if there are multiple js files to be loaded, these codes will be executed sequentially.
Since JavaScript codes may operate HTML DOM tree, browsers generally will not download js files in parallel like downloading css files.If you want the JavaScript codes to operate some DOM elements which are not loaded yet, the browser will throw out object cannot be found error.
The traditional method
When we use below code to load js file:
<script type="text/javascript" src="http://coolshell.cn/asyncjs/alert.js"></script>
The <script> tag in the head section will block the subsequent resource loading and the generation of the whole page. Here is a demo page : Demo 1,There is only one statement in alert.js which is alert("hello world");,This will be very easy for you to see how JavaScript blocks other resources.
So this is why many websites put the JavaScript codes at the end of the page, we can use window.onload and document.ready events to do this. In addition, because most JavaScript codes will execute without waiting for other page elements, we can load JavaScript codes asynchronously.
document.write
We may use document.write to load JavaScript codes in a non-blocking way. You may think that the codes after document.write will execute automatically after they are executed. This is not wrong, for the codes in the same script tag, it's right, but to the whole page, it will still block the following contents.
<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 is the order of different alert statements above? Here is another demo : Demo 2.
defer and async in JavaScript
IE starts to support defer since IE 6.
<script defer type="text/javascript" src="./alert.js" ></script>
As for IE, this attribute will allow IE to download js files in parallel and the downloaded js file will be executed after DOM tree loaded(DOMContentLoaded), It will not block the following DOM rendering after defer attribute set in a script tag. But defer is only available in IE, so it's not cross browser compatible.
In HTML5, there is one more attribute called async. No matter value you assign to it, the js file will loaded asynchronously. However there is a serious issue about async loading which is the JavaScript codes will execute immediately on loading.
Browsers supporting async are Firefox3.6+,Chrome 8.0+,Safari 5.0+,IE 10+. Opera doesn't support this attribute yet.
Dynamically creating DOM
This method is most frequently used:
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 is almost the standard method for asynchronously loading js file, the demo for this is Demo 3. This method also introduces a new thing called JSONP, we can specify PHP script for the src attribute of script tag, this PHP script will return a JavaScript function, the parameter is a JSON string.
Loading js as needed
The above method solves the asynchronous loading issue, but it doesn't solve the issue when the script should executed. So we need to bind the above DOM method onto some specified events.
For example:
Binding it on window.load--Demo 4
window.load = loadjs("http://coolshell.cn/asyncjs/alert.js")
Binding it on some other events -- Demo 5
<p style="cursor: pointer" onclick="LoadJS()">Click to load alert.js </p>
This demo is quite simple, it will load the alert.js only after you click the button
What's next
We may want to download the js file first and execute it only when we want it to be executed. The following method is what we want:
var script = document.createElement("script"); script.noexecute = true; script.src = "alert.js"; document.body.appendChild(script); //We can execute by calling this script.execute();
The sad thing is this is only a beatiful dream, JavaScript doesn't support this yet. So we need to use some hacks. Some people use non-standard type cache//javascript in script tag.
<script type=cache/script src="./alert.js"></script>
cache/script cannot be recognized by browser, so browser will not execute alert.js. but it will download this file. This type is not supported by webkit.
So we may need one more hack:
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); }
Here is one demo for above methid : Demo 6.
At last, there are two JS libraries named ControlJS and HeadJS which are used to load JavaScript files asynchronously.
Author : 陈皓 Source : http://coolshell.cn/articles/9749.html