ES6 Module的加载

注:这是一篇学习笔记,记录自己在ES6学习过程中按照自己的思路觉得应该记录的一些要点,方便以后查看和复习。参考:

阮一峰ES6的书籍中Module 的加载实现
我的ES6入门学习规划

浏览器中加载脚本

<script>标签可以添加defer或async属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令。

defer与async的区别是:defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

script标签也可以用来加载es6的模块,加上type=”module”即可:

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="module" src="./es6_module_04.js" />
</head>
<body>
</body>
</html>

浏览器对于带有type=”module”的script,都是异步加载,等同于打开了defer属性,async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。一旦使用了async属性,type=”module”的script就不会按照在页面出现的顺序执行,而是只要该模块加载完成,就执行该模块。

script标签也可以直接用来定义es6模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="module" >
import * as m from "./es6_module_04.js";

// other module logic
</script>
</head>
<body>
</body>
</html>

type=”module”的script引入的外部脚本,需要注意:

  • 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见
  • 模块之中,顶层的this关键字返回undefined,而不是指向window。也就是说,在模块顶层使用this关键字,是无意义的

总之,不论是外部的es6模块脚本,还是内嵌的es6模块脚本,它都要遵循上一篇笔记记录的所有module的特性;浏览器最终只是module加载和被使用的位置,不会违背语言规范定出的规则。

node中加载es6的module

这个部分的内容还没有统一起来,暂时学的兴趣不大。

循环加载

cmd是动态加载,es6是静态加载,所以在处理循环加载时区别比较大。

cmd的循环加载

为了避免重复,这个部分可完全参考CommonJS 模块的循环加载

es6的循环加载

为了避免重复,这个部分可完全参考ES6 模块的循环加载

理解这个部分的要点还是es6模块的核心知识点:静态加载,每个模块的接口,在编译完成就已经确定了,但是值不确定,模块内部的逻辑要保证当接口真正被使用的那一刻,接口能够按照预期发挥作用。 正是因为这一点,当“module A引用了module B,B也在内部引用了A”这种情况发生时,不管是哪个moduel先被其它module使用,A或B都不用等到对方执行完毕,就能知道对方有什么接口,所以可以很大胆地去使用对方的接口,只不过由于循环加载总会导致一方需等到另一方执行完毕才能继续自己的加载逻辑,被等待的一方可能会因为等待方的逻辑未执行完,而在使用等待方的接口时发生错误。 只要明白了这个点,就能帮助自己去分析和解决循环加载的问题。

其它

es6的模块目前在较高版本的浏览器中是可用的,但是低版本的浏览器还不能使用,所以在实际工作中,需要转码。