


This article is mainly based on several ways to introduce JavaScript into HTML pages, analyzing the execution order of JavaScript scripts in HTML
1. Regarding the blocking nature of JavaScript script execution
JavaScript has blocking characteristics when it is parsed and executed in the browser. That is to say, when the JavaScript code is executed, the parsing, rendering and downloading of other resources must stop and wait for the script to complete①. This is uncontroversial, and the behavior is consistent in all browsers. The reason is not difficult to understand: the browser needs a stable DOM structure, and JavaScript may modify the DOM (change the DOM structure or modify a certain DOM node), if the parsing of the page continues while JavaScript is being executed, the entire parsing process will become difficult to control, and the possibility of parsing errors will also become very high.
However, there is another issue that needs attention here. For external scripts, it also involves a script download process. In early browsers, the download of JavaScript files would not only block the parsing of the page, but even block other resources on the page. Downloads (including other JavaScript script files, external CSS files, and external resources such as images). Starting from IE8, Firefox3.5, Safari4 and Chrome2, parallel downloading of JavaScript is allowed. At the same time, the downloading of JavaScript files will not block the downloading of other resources (in older versions, the downloading of JavaScript files will also block the downloading of other resources).
Note: Different browsers have different restrictions on the maximum number of connections under the same domain name. The requirement in the HTTP1.1 protocol specification is that it cannot be higher than 2, but most browsers currently provide a maximum number of connections. More than 2, IE6/7 both have 2, IE8 has been upgraded to 6, firefox and chrome also have 6. Of course, this setting can also be modified. For details, please refer to: http://www.stevesouders. com/blog/2008/03/20/roundup-on-parallel-connections/
2. About the execution order of the script
Browsers parse pages in order from top to bottom, so under normal circumstances, the execution order of JavaScript scripts is also from top to bottom, that is, the code that appears first on the page or the code that is introduced first is always executed first. execution, even when parallel downloading of JavaScript files is allowed. Note that we have marked "under normal circumstances" in red here. What is the reason? We know that there are many ways to add JavaScript code to HTML, which are summarized as follows (regardless of module loaders such as requirejs or seajs):
(1) Normal introduction: that is, introducing script code or introducing external scripts through the <script> tag in the page <br /> </script>
(2) Write <script> tags or codes to the page through the document.write method <br /> </script>
(3) Through dynamic script technology, that is, using the DOM interface to create a <script> element, setting the src of the element, and then adding the element to the DOM. <br /> </script>
(4) Obtain the script content through Ajax, then create the <script> element, set the text of the element, and then add the element to the DOM. <br /> </script>
(5) Write JavaScript code directly in the event handler of the element or directly as the body of the URL. The example is as follows:
<!--直接写在元素的事件处理程序中--> <input type="button" value="点击测试一下" onclick="alert('点击了按钮')"/> <!--作为URL的主体--> <a href="javascript:alert('dd')">JS脚本作为URL的主体</a>
The fifth case has no impact on the script execution order we are discussing, so we only discuss the first four cases here:
2.1 When introducing script normally
When a script is normally introduced, the JavaScript code will be executed from top to bottom. Regardless of whether the script is downloaded in parallel, it will still be executed from top to bottom in the order of introduction. Let’s take the following DEMO as an example:
First, write a script through PHP. This script receives two parameters, the file URL and the delay time. The script will send the file content to the browser after the incoming delay time. The script is as follows:
<?php $url = $_GET['url']; $delay = $_GET['delay']; if(isset($delay)){ sleep($delay); } echo file_get_contents($url); ?>
In addition, we have also defined two JavaScript files, namely 1.js and 2.js. In this example, the codes of the two are as follows:
1.js
alert("I am the first script");
2.js
alert("I am the second script");
Then, we introduce the script code in HTML:
<script src='/delayfile.php?url=http://localhost/js/load/1.js&delay=3' type='text/javascript'></script> <script type="text/javascript"> alert("我是内部脚本"); </script> <script src='/delayfile.php?url=http://localhost/js/load/2.js&delay=1' type='text/javascript'></script>
虽然第一个脚本延迟了3秒才会返回,但是在所有浏览器中,弹出的顺序也都是相同的,即:"我是第一个脚本"->"我是内部脚本"->"我是第二个脚本"
2.2 通过document.write向页面中写入脚本时
document.write在文档流没有关闭的情况下,会将内容写入脚本所在位置结束之后紧邻的位置,浏览器执行完当前短的代码,会接着解析document.write所写入的内容。
注:document.write写入内容的位置还存在一个问题,加入在
内部的脚本中写入了标签内部不应该出现的内容,比如通过document.write写入脚本时存在一些问题,需要分类进行说明:
[1]同一个<script>标签中通过document.write只写入外部脚本:<br /> </script>
在这种情况下,外部脚本的执行顺序总是低于引入脚本的标签内的代码,并且按照引入的顺序来执行,我们修改HTML中的代码:
<script src='/delayfile.php?url=http://localhost/js/load/1.js&delay=2' type='text/javascript'></script> <script type="text/javascript"> document.write('<script type="text/javascript" src="/delayfile.php?url=http://localhost/js/load/2.js"><\/script>'); document.write('<script type="text/javascript" src="/delayfile.php?url=http://localhost/js/load/1.js"><\/script>'); alert("我是内部脚本"); </script>
这段代码执行完毕之后,DOM将被修改为:
而代码执行的结果也符合DOM中脚本的顺序:"我是第一个脚本"->"我是内部脚本"->"我是第二个脚本"->"我是第一个脚本"
[2]同一个<script>标签中通过document.write只写入内部脚本:<br /> </script>
在这种情况下,通过documen.write写入的内部脚本,执行顺序的优先级与写入脚本标签内的代码相同,并且按照写入的先后顺序执行:
我们再修改HTML代码如下:
<script src='/delayfile.php?url=http://localhost/js/load/1.js' type='text/javascript'></script> <script type="text/javascript"> document.write('<script type="text/javascript">alert("我是docment.write写入的内部脚本")<\/script>'); alert("我是内部脚本"); document.write('<script type="text/javascript">alert("我是docment.write写入的内部脚本2222")<\/script>'); document.write('<script type="text/javascript">alert("我是docment.write写入的内部脚本3333")<\/script>'); </script>
在这种情况下,document.write写入的脚本被认为与写入位置处的代码优先级相同,因此在所有浏览器中,弹出框的顺序均为:"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是document.write写入的内部脚本2222"->"我是document.write写入的内部脚本3333"
[3]同一个<script>标签中通过document.write同时写入内部脚本和外部脚本时:<br /> </script>
在这种情况下,不同的浏览器中存在一些区别:
在IE9及以下的浏览器中:只要是通过document.write写入的内部脚本,其优先级总是高于document.write写入的外部脚本,并且优先级与写入标签内的代码相同。而通过通过document.write写入的外部脚本,则总是在写入标签的代码执行完毕后,再按照写入的顺序执行;
而在其中浏览器中, 出现在第一个document.write写入的外部脚本之前的内部脚本,执行顺序的优先级与写入标签内的脚本优先级相同,而之后写入的脚本代码,不管是内部脚本还是外部脚本,总是要等到写入标签内的脚本执行完毕后,再按照写入的顺序执行。
我们修改以下HTML中的代码:
<script src='/delayfile.php?url=http://localhost/js/load/1.js' type='text/javascript'></script><script type="text/javascript"> document.write('<script type="text/javascript">alert("我是docment.write写入的内部脚本")<\/script>'); alert("我是内部脚本"); document.write('<script type="text/javascript" src="/delayfile.php?url=http://localhost/js/load/1.js"><\/script>'); document.write('<script type="text/javascript">alert("我是docment.write写入的内部脚本2222")<\/script>'); document.write('<script type="text/javascript" src="/delayfile.php?url=http://localhost/js/load/1.js"><\/script>'); document.write('<script type="text/javascript">alert("我是docment.write写入的内部脚本3333")<\/script>'); alert("我是内部脚本2222");</script>
在IE9及以下的浏览器中,上面代码执行后弹出的内容为:"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是document.write写入的内部脚本2222"->"我是document.write写入的内部脚本3333"->"我是内部脚本2222"->"我是第一个脚本"->"我是第一个脚本"
其他浏览器中,代码执行后弹出的内容为:"我是第一个脚本"->"我是document.write写入的内部脚本"->"我是内部脚本"->"我是内部脚本2222"->"我是第一个脚本"->"我是document.write写入的内部脚本2222"->"我是第一个脚本"->"我是document.write写入的内部脚本3333"
如果希望IE及以下的浏览器与其他浏览器保持一致的行为,那么可选的做法就是把引入内部脚本的代码拿出来,单独放在后面一个新的<script>标签内即可,因为后面<script>标签中通过document.write所引入的代码执行顺序肯定是在之前的标签中的代码的后面的。<br /> </script>
2.3 通过动态脚本技术添加代码时
通过动态脚本技术添加代码的主要目的在于创建无阻塞脚本,因为通过动态脚本技术添加的代码不会立刻执行,我们可以通过下面的load函数为页面添加动态脚本:
function loadScript(url,callback){ var script = document.createElement("script"); script.type = "text/javascript"; //绑定加载完毕的事件 if(script.readyState){ script.onreadystatechange = function(){ if(script.readyState === "loaded" || script.readyState === "complete"){ callback&&callback(); } } }else{ script.onload = function(){ callback&&callback(); } } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
但是通过动态脚本技术添加的外部JavaScript脚本不保证按照添加的顺序执行,这一点可以通过回调或者使用jQuery的html()方法,详细可参考:http://www.jb51.net/article/26446.htm
2.4 通过Ajax注入脚本
通过Ajax注入脚本同样也是添加无阻塞脚本的技术之一,我们首先需要创建一个XMLHttpRequest对象,并且实现get方法,然后通过get方法取得脚本内容并注入到文档中。
代码示例:
我们可以用如下代码封装XMLHttpRequest对象,并封装其get方法:
var xhr = (function(){ function createXhr(){ var xhr ; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else if(window.ActiveXObject){ var xhrVersions = ['MSXML2.XMLHttp','MSXML2.XMLHttp.3.0','MSXML2.XMLHttp.6.0'], i, len; for(i = 0, len = xhrVersions.length; i < len ; i++){ try{ xhr = new ActiveXObject(xhrVersions[i]); }catch(e){ } } }else{ throw new Error("无法创建xhr对象"); } return xhr; } function get(url,async,callback){ var xhr = createXhr(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ callback&&callback(xhr.responseText); }else{ alert("请求失败,错误码为" + xhr.status); } } } xhr.open("get",url,async); xhr.send(null); } return { get:get } }())
然后基于xhr对象,再创建loadXhrScript函数:
function loadXhrScript(url,async, callback){ if(async == undefined){ async = true; } xhr.get(url,async,function(text){ var script = document.createElement("script"); script.type = "text/javascript"; script.text = text; document.body.appendChild(script); });}
我们上面的get方法添加了一个参数,即是否异步,那么如果我们采用同步方法,通过Ajax注入的脚本肯定是按照添加的顺序执行;反之,如果我们采用异步的方案,那么添加的脚本的执行顺序肯定是无法确定的。

Detailed explanation of JavaScript string replacement method and FAQ This article will explore two ways to replace string characters in JavaScript: internal JavaScript code and internal HTML for web pages. Replace string inside JavaScript code The most direct way is to use the replace() method: str = str.replace("find","replace"); This method replaces only the first match. To replace all matches, use a regular expression and add the global flag g: str = str.replace(/fi

This tutorial shows you how to integrate a custom Google Search API into your blog or website, offering a more refined search experience than standard WordPress theme search functions. It's surprisingly easy! You'll be able to restrict searches to y

So here you are, ready to learn all about this thing called AJAX. But, what exactly is it? The term AJAX refers to a loose grouping of technologies that are used to create dynamic, interactive web content. The term AJAX, originally coined by Jesse J

This article series was rewritten in mid 2017 with up-to-date information and fresh examples. In this JSON example, we will look at how we can store simple values in a file using JSON format. Using the key-value pair notation, we can store any kind

Leverage jQuery for Effortless Web Page Layouts: 8 Essential Plugins jQuery simplifies web page layout significantly. This article highlights eight powerful jQuery plugins that streamline the process, particularly useful for manual website creation

Core points This in JavaScript usually refers to an object that "owns" the method, but it depends on how the function is called. When there is no current object, this refers to the global object. In a web browser, it is represented by window. When calling a function, this maintains the global object; but when calling an object constructor or any of its methods, this refers to an instance of the object. You can change the context of this using methods such as call(), apply(), and bind(). These methods call the function using the given this value and parameters. JavaScript is an excellent programming language. A few years ago, this sentence was

jQuery is a great JavaScript framework. However, as with any library, sometimes it’s necessary to get under the hood to discover what’s going on. Perhaps it’s because you’re tracing a bug or are just curious about how jQuery achieves a particular UI

This post compiles helpful cheat sheets, reference guides, quick recipes, and code snippets for Android, Blackberry, and iPhone app development. No developer should be without them! Touch Gesture Reference Guide (PDF) A valuable resource for desig


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SublimeText3 Mac version
God-level code editing software (SublimeText3)

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Zend Studio 13.0.1
Powerful PHP integrated development environment
