模块(Module)是自动运行在严格模式下并且没有办法退出运行的JavaScript代码。
this的值是undefined可以用export关键字将任意变量、函数或类声明从模块中导出。除非用default关键字,否则不能用export导出匿名函数或类
模块的导出可以通过import关键字在另一个模块中访问。
import后面的大括号表示从给定模块导入的绑定(binding)。
导入绑定的列表看起来和解构对象很像,但它不是
关键字from表示从哪个模块导入。由表示模块路径的字符串指定。
<script>元素的相同,必须加上扩展名Node.js则遵循基于文件系统前缀区分本地文件和包的习惯从模块中导入的绑定,和常量const类似,不能存在同名变量,也无法在import语句前使用标识符或改变绑定的值
可以使用as关键字将整个模块作为一个单一对象导入。该模块的所有导出都可以作为对象的属性使用。
一个模块不管被import了几次,都只执行一次。
export和import的一个重要限制是必须在其他语句和函数之外使用
当导入或者导出变量、函数或者类时,可以用as关键字改变名称。
模块的默认值是指通过default关键字指定的单个变量、函数或类。只能为每个模块设置一个默认导出值。
另外还可以通过重命名来导出默认值,上例可以改成:
ES6定义了模块语法,但是并没有定义如何加载这些模块。加载机制由一个未定义的内部抽象方法HostResolveImportedModule决定,浏览器和Node.js可以自己实现。
在<script>中将type设置为module时,支持加载模块。为了保证模块的加载顺序,<script type="module">在执行时,自动应用defer属性。因此,所以的模块组件在文档被解析完才会执行。
由于每个模块都可以从其他模块导入,因此在加载阶段,该模块加载完之后会识别所有导入语句,然后每个导入语句都出发一次获取过程,并且在所有导入资源都被加载之后,执行当前模块。
以如下代码为例:
完整的加载顺序如下:
module1.jsmodule1.js中导入的模块module2.jsmodule2.js中导入的模块加载完成之后,只有当文档完全被解析之后才会执行以下操作:
module1.js中导入的模块module1.jsmodule2.js中导入的模块module2.js与通用脚本加载一样,模块也支持async属性,设置之后,会以异步方式加载。异步加载的模块不必等待文档解析完成,但是需要模块中所有导入文件都加载完成,才会执行模块。但是无法保证模块的先后执行顺序,而是哪个模块及其依赖模块先加载完就先执行哪个模块。
Worker加载通过配置Worker的第二个参数,可以支持以模块方式加载。
以脚本方式加载的Worker与以模块方式加载的Worker存在以下两点不同:
Worker脚本只能引用与网页同源的JavaScript,而Worker模块不会完全受限,可以加载并访问具有适当的跨域资源共享(CORS)头的文件。Worker脚本可以使用self.importScripts()加载其他脚本,但Worker模块不能,而是应该使用import来导入。在浏览器中,模块说明符(module specifier)只支持以下四种格式:
/开头,从根目录开始解析./开头,从当前目录开始解析../开头,从父级目录开始解析以下的格式,是无效的,并且会导致错误