有时我们需要在javascript脚本中创建js文件,那么在javascript脚本中创建的js文件又是如何执行的呢?和我们直接在HTML页面种写一个script标签的效果是一样的吗?(关于页面script脚本的执行可看webkit技术内幕读书笔记 (四)中的资源加载一节)这是今天我要研究的对象。

为了测试,我分别创建了一个html页面,和两个js文件,具体如下

index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
  <h2>h2</h2>
  <script>
    var script1 = document.createElement("script");
    script1.src = "http://127.0.0.1:8081/index.js";
    document.body.appendChild(script1);

    var script2 = document.createElement("script");
    script2.src = "index2.js";
    document.body.appendChild(script2);

    console.log("script ok");
  </script>
  <h3>h3</h3>
</body>
</html>
index.js
var http = require("http");

http.createServer(function(req,res){

}).listen(8081);
index2.js
console.log("index2.js");

其中index.js的作用是,拖住浏览器的执行,始终不给浏览器响应,以上代码的执行效果如下图

对动态加载javascript脚本的研究_加载

可以看到它并没有按照我编写代码的顺序来执行,也就是说通过这种方式创建的script脚本是异步执行的,准确的说是appendChild方法导致script脚本是异步的,因为如果只是去创建script文件,浏览器是不会去加载js文件的。如下我将appendChild注释掉

    var script1 = document.createElement("script");
    script1.src = "http://127.0.0.1:8081/index.js";
//    document.body.appendChild(script1);

    var script2 = document.createElement("script");
    script2.src = "index2.js";
//    document.body.appendChild(script2);
    console.log("script ok");

效果如下图

对动态加载javascript脚本的研究_html_02

可以看到并没有发送下载js文件请求,对于appendChild为什么要弄成异步的,暂时不得而知。

我们再来看看innerHTML的方式添加script脚本

index.html
<h2>h2</h2>
<script>
    document.body.innerHTML += "<script src='http://127.0.0.1:8081/index.js'><\/script>";
    document.body.innerHTML += "<script src='index2.js'><\/script>";
</script>
<h3>h3</h3>

经过测试,发现以上两个js文件并没有被执行,甚至连下载的请求都没有,如下图

对动态加载javascript脚本的研究_firefox_03

难道是因为innerHTML只是把内容当成HTML来解析?这个目前还不得而知,只是我奇怪的是,innerHTML对style标签又会进行解析,效果如下

对动态加载javascript脚本的研究_javascript_04

代码为

<h2>h2</h2>
<script>
    document.body.innerHTML += "<script src='http://127.0.0.1:8081/index.js'><\/script>";
    document.body.innerHTML += "<style>h2{color:red}<\/style>";
</script>
<h3>h3</h3>

然后我再想,难道是不能写外部脚本?于是我将代码换成如下

<h2>h2</h2>
<script>
    document.body.innerHTML += "<script src='http://127.0.0.1:8081/index.js'><\/script>";
    document.body.innerHTML += "<script>alert('script')<\/script>";
</script>
<h3>h3</h3>

其结果依然没有被执行,如图

对动态加载javascript脚本的研究_html_05

听网上说“script标签中的脚本仅在浏览器第一次加载页面时对其进行解析并执行”,如果按照这样说的话,那么为什么appendChild却可以?郁闷

推荐阅读:

IE 和 Firefox 可以通过特定方法使 innerHTML 方法载入的 SCRIPT 标签中的 JavaScript 代码在页面加载后也可以执行

看看document.write是如何执行的

代码如下

<h2>h2</h2>
<script>
    document.write("<script src='http://127.0.0.1:8081/index.js'><\/script>");
    document.write("<script src='index2.js'><\/script>");
</script>
<h3>h3</h3>

执行后,结果代码被堵塞了,如下图

对动态加载javascript脚本的研究_加载_06

通过document.write的方式来加载script和直接在页面中写script标签的执行过程基本相同。