1.在es6之前,社区制定了一些模块加载方案,最主要的有CommonJS 和AMD两种。前者用于服务器,后者用于浏览器。es6在语言标准的层面,实现了模块功能,实现简单,完全可以取代CommomJS和AMD模块,成为浏览器与服务器通用的模块解决方案。
es6模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommomJS和AMD模块,都只在运行时确定这线东西。
es6模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
除了静态加载带来的各种好处,ES6 模块还有以下好处。
- 不再需要
UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点。 - 将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者
navigator对象的属性。 - 不再需要对象作为命名空间(比如
Math对象),未来这些功能可以通过模块提供。
2.ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。
3.export命令:用于规定模块的对外接口
// 报错
export 1;
// 报错
var m = 1;
export m;
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
// 报错
function f() {}
export f;
// 正确
export function f() {};
// 正确
function f() {}
export {f};
4.import命令
使用import命令输入的变量都是只读的
foo();
import { foo } from 'my_module';
上面的代码不会报错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。由于import是静态执行,所以不能使用表达式和变量(这些是运行时才能得到结果的语法结构)。
5.export default命令
// 第一组
export default function crc32() { // 输出
// ...
}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出
// ...
};
import {crc32} from 'crc32'; // 输入
//上面代码的两组写法,第一组是使用export default时,对应的import语句不需要使用大括号;第二组是不使用export default时,对应的import语句需要使用大括号。
6.浏览器加载
<!-- 执行完脚本,再继续向下执行 -->
<script type="application/javascript" src="path/to/myModule.js">
<!-- 整个页面在内存中正常渲染结束(Dom结果生成,其他脚本执行完成) -->
<script src="path/to/myModule.js" defer></script>
<!-- 一旦下载完,渲染就会中断渲染,执行这个脚本以后,再继续渲染 -->
<script src="path/to/myModule.js" async></script>
一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
7.浏览器加载模块的规则
浏览器加载 ES6 模块,也使用<script>标签,但是要加入type="module"属性。
<script type="module" src="./foo.js"></script>
浏览器对于带有type="module"的<script>,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性。
ES6 模块也允许内嵌在网页中,语法行为与加载外部脚本完全一致。
<script type="module">
import utils from "./utils.js";
// other code
</script>
对于外部的模块脚本(上例是foo.js),有几点需要注意。
- 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。
- 模块脚本自动采用严格模式,不管有没有声明
use strict。 - 模块之中,可以使用
import命令加载其他模块(.js后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用export命令输出对外接口。 - 模块之中,顶层的
this关键字返回undefined,而不是指向window。也就是说,在模块顶层使用this关键字,是无意义的。 - 同一个模块如果加载多次,将只执行一次。
ES6模块提供了静态加载的解决方案,优于CommonJS和AMD,适用于服务器和浏览器。模块通过export导出和import导入,且import的变量为只读。export default允许设置默认导出。浏览器加载模块异步且不阻塞渲染,使用script标签并指定type。模块运行在严格模式下,顶层变量对外部不可见,且关键字如return无效。

2016

被折叠的 条评论
为什么被折叠?



