同步加载和执行JS的情况

在HTML页面的</body>表情之前添加的所有<script>标签,无论是直接嵌入JS代码还是引入外部js代码都是同步执行的,这里的同步执行指的是在加载好和执行完JS代码之前整个浏览器的界面都是阻塞的。

静态加载时

内嵌代码和引入js代码都是同步加载。

动态加载时

通过document.write('<script src="xxx.js"></script>');的方式加入的代码也是同步加载的,但是要注意一点,这里开始加载和解析xxx.js是在执行完成当前的<script>标签之后,所以下面的代码会报错(我们假设test.js中创建了全局的p对象,且该对象存在sayHi的方法):

 <script>
console.log("sync load js");
document.write('<script src="test.js"></script>');
console.log(p.sayHi());
</script>

根据我们说的开始加载和解析xxx.js是在执行完成当前的<script>标签之后,可以把上面的代码转换如下:

 <script>
console.log("sync load js");
console.log(p.sayHi());
</script>
<script src="test.js"></script>

这样必然会出错,如下则可以正常执行:

 <script>
console.log("sync load js");
document.write('<script src="test.js"></script>');
</script>
<script>
console.log(p.sayHi());
</script>

document.write方式同步加载外部js文件无论是内嵌的写法还是写在外部js文件中,效果都是一样的,都会同步加载和执行。

异步加载和执行JS的情况

静态加载时

对于内嵌的JS代码只能同步执行,对于通过<script>标签引入的外部js文件,可以通过设定defer和async两个属性改变为异步加载执行。

defer

代码如下:<script src="xxx.js" defer></script>,该属性在HTML4.01引入,告诉浏览器立即下载该脚本(下载期间不阻塞页面),但是等待遇到</html>标签之后再执行,同时执行顺序按照标签出现顺序进行执行。该脚本的执行一定会在页面的load事件之前。

async

代码如下:<script src="xxx.js" async></script>,该属性在HTML5引入,告诉浏览器立即下载该脚本(下载期间不阻塞页面),但是执行脚本时不能保证按照标签出现顺序执行。该脚本的执行一定会在页面的load事件之前。

最佳实践

由于浏览器的支持不同,所以最好的方法仍然是将<script src="xxx.js"></script>脚本放在页面的最下方引入。

动态加载时

如果我们希望在页面任意时刻动态异步加载js文件,可以通过使用DOM元素创建方法来实现:

 var script = document.createElement("script");
script.type = "text/javascript";
script.src = "xxx.js";
document.getElementsByTagName("head")[0].appendChild(script);

当script元素被添加到页面之后便开始下载脚本文件。该技术的优点是:无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。当script文件下载完成后,返回的代码通常被立即执行(除了FF和Opera,它们将等待此前的所有动态脚本节点执行完毕。)

唯一的问题是我们需要知道动态加载的脚本何时完成加载并可以使用,FF, Opera, Chrome和Safari3+会在节点接收完成后发出一个load事件;IE则是发出一个readystatechange事件,<script>元素有一个readyState属性,它的值随着下载过程而改变。readyState有5种取值:uninitialized(默认状态),loading(下载开始),loaded(下载完成),interactive(下载完成但尚不可用),complete(所有数据已准备好)。

最终的代码如下:

 function loadScript(url, callback){
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) { // IE
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else { // FF, Chrome, Opera, ...
script.onload = function() {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}

如果要加载多个文件,并且要保证顺序,则可以采用将上述函数串联的方式实现。

 loadScript("../scripts/test1.js", function(){
loadScript("../scripts/test2.js", function(){
loadScript("../scripts/test3.js", function(){
test3.print("hi, i'm abc.");
})
});
});

如果觉得这种嵌入的写法太不爽,也可以稍作修改改为Promise的写法。

HTML5学习笔记(二十三):DOM应用之动态加载脚本的更多相关文章

  1. AntDesign vue学习笔记(五)导航菜单动态加载

    一般的后台系统都有一个树形导航菜单,具体实现如下,主要参考https://my.oschina.net/u/4131669/blog/3048416 "menuList": [ { ...

  2. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  3. Android 学习笔记之Volley(七)实现Json数据加载和解析...

    学习内容: 1.使用Volley实现异步加载Json数据...   Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...

  4. Redis深入学习笔记(一)Redis启动数据加载流程

    这两年使用Redis从单节点到主备,从主备到一主多从,再到现在使用集群,碰到很多坑,所以决定深入学习下Redis工作原理并予以记录. 本系列主要记录了Redis工作原理的一些要点,当然配置搭建和使用这 ...

  5. Ext JS学习第十天 Ext基础之动态加载JS文件(补充)

    此文用来记录学习笔记: •Ext4.x版本提供的一大亮点就是Ext.Loader这个类的动态加载机制!只要遵循路径规范,即可动态加载js文件,方便把自己扩展组件动态加载进来,并且减轻浏览器的压力. • ...

  6. Javascript学习笔记二——操作DOM

    Javascript学习笔记 DOM操作: 一.GetElementById() ID在HTML是唯一的,getElementById()可以定位唯一的一个DOM节点 二.querySelector( ...

  7. (C/C++学习笔记) 二十三. 运行时类型识别

    二十三. 运行时类型识别 ● 定义 运行时类型识别(Run-time Type Identification, RTTI) 通过RTTI, 程序能够使用基类的指针或引用来检查(check)这些指针或引 ...

  8. Java基础学习笔记二十三 Java核心语法之反射

    类加载器 类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,链接,初始化三步来实现对这个类进行初始化. 加载就是指将class文件读入内存,并为之创建一个Class对象.任 ...

  9. Windows调试学习笔记:(一)WinDBG中加载SOS和CLR

    最近产品环境出现了部分服务器当机情况,虽然重启之后问题就不出现了.但本着彻底解决问题的态度,想要找到root cause.多次尝试Visual Studio失败(可能是代码惊醒了优化和签名)之后,决定 ...

随机推荐

  1. Axure 实现数字自动加键功能(点击“+”数字加1,点击“-”数字减1)

    百度网盘:http://pan.baidu.com/s/1gfPQ9V1 在上面的元件库中,拖“数字框(仅正数)”即可实现自动加减的功能 如图:

  2. N皇后问题【递归求解】

    n皇后问题:输入整数n, 要求n个国际象棋的皇后,摆在n*n的棋盘上,互相不能攻击,输出全部方案. 输入一个正整数N,则程序输出N皇后问题的全部摆法.输出结果里的每一行都代表一种摆法.行里的第i个数字 ...

  3. hdu 4122 Alice&#39;s mooncake shop (线段树)

    题目大意: 一个月饼店每一个小时做出月饼的花费不一样. 储存起来要钱.最多存多久.问你把全部订单做完的最少花费. 思路分析: ans = segma( num[]*(cost[] + (i-j)*s) ...

  4. webdriver之py,driver启动chrome时加载profile

    import os from selenium import webdriver from selenium.webdriver.chrome.options import Options execu ...

  5. 如何用STAF进行自动化测试分布式运行

    本文的目的在于引导读者去了解STAF及如何调用其接口去实现自动化测试的分布式动行. 提到分布式运行,很多人想到了Jenkins,Jenkins里面有个node插件,可以去分派任务给slave,Jenk ...

  6. Fedora下使用minicom及USB串口线

    一.minicom Fedora不像以前的RedHat,不能直接输入minicom回车,因为在目录/dev/下面没有modem这个子目录,而minicom的运行默认是有这个目录的,所以直接敲是不行的. ...

  7. 【Spring】SpringMVC中浅析数据的传递方式

    包括了基本数据类型的传递和 Date数据类型的传递.关于SpringMVC的配置可以参见基于注解实现SpringMVC+MySQL 假设有表单页面如下: <h1>登录</h1> ...

  8. ios面试题来一波

    一.如果让你实现属性的weak,如何实现的? PS: @property 等同于在.h文件中声明实例变量的get/set方法, 而其中property有一些关键字,其中就包括weak,atomic的. ...

  9. 【Linux】进程优先级、进程nice值和%nice

    用top或者ps命令会输出PRI/PR.NI.%ni/%nice这三种指标值,这些到底是什么东西?先给出大概的解释如下: PRI :进程优先权,代表这个进程可被执行的优先级,其值越小,优先级就越高,越 ...

  10. 如何快速学会android的四大基础----Service篇

    很多人都以为,只要学过一点java就可以马上写android应用了,这种想法的产生非常自然,因为现在网上有那么多的android开源实例,只要跟着来,也能够自己写一个播放器.但是,只有去写一个真正投入 ...