Module的语法和加载实现

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.浏览器加载




一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

7.浏览器加载模块的规则

浏览器加载 ES6 模块,也使用

浏览器对于带有type="module"

对于外部的模块脚本(上例是foo.js),有几点需要注意。

  • 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。
  • 模块脚本自动采用严格模式,不管有没有声明use strict
  • 模块之中,可以使用import命令加载其他模块(.js后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用export命令输出对外接口。
  • 模块之中,顶层的this关键字返回undefined,而不是指向window。也就是说,在模块顶层使用this关键字,是无意义的。
  • 同一个模块如果加载多次,将只执行一次。

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(ES6)