企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] ***** ## 1 模块意义 1. 模块将大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。 2. 模块加载方案之前,最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。 3. ES6在语言规格的层面上,实现了模块功能,实现得相当简单,完全可以取代现有的CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方法 4. CommonJs和AMD模块则是在运行时确定,生成模块对象,输入时必须查找对象属性,这种加载称为运行时加载,完全没有静态化。 5. ES6的模块尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。ES6模块不是对象,通过export命令显式指定输出的代码,输入采用静态命令的形式。这种加载称为编译时加载。 ## 2 模块的简单使用 1. 模块功能主要由两个命令构成 export和import,export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能 ## 3 export命令 1. 模块通常实现为独立的文件。内部的所有变量,外部无法获取,可以使用export命名导出该变量。第一种写法就是声明式导出。 ~~~ export var firstName = 'Michael'; export var lastName = 'Jackson'; export var year = 1958; ~~~ 2. 整体导出。首先考虑下面这种写法。可以在脚本尾部,一眼看清楚输出了哪些变量 ~~~ // profile.js var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year}; ~~~ 3. 除了输出变量,还可以输出函数或类 ~~~ export function multiply (x, y) { return x * y; }; ~~~ ~~~ function v1() { ... } function v2() { ... } export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion }; ~~~ 4. 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}; ~~~ 5. export语句输出的接口,与对应的值是动态绑定关系,可以通过该接口,取到模块内部实时的值 ~~~ export var foo = 'bar'; setTimeout(() => foo = 'baz', 500); ~~~ 6. ES6模块与CommonJS规范完全不同。CommmonJS模块输出的是值的缓存,不存在动态更新。ES6模块的import与export命名只可以用在模块顶层,处于块级作用内,就会报错。 ## 4 import命令 1. 使用export命令导出的即可,使用其他JS文件可以通过import命令加载这个模块文件 ~~~ // main.js import {firstName, lastName, year} from './profile'; function setName(element) { element.textContent = firstName + ' ' + lastName; } ~~~ 2. import 命令用于加载profile.js文件,从中输出变量。import命令接受一个对象,里面指定从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块对外接口的名称相同 3. 可以使用as关键字,将输入变量重新命名 ~~~ import { lastName as surname } from './profile'; ~~~ 4. import命令具有提升效果,会提升到整个模块的头部,首先执行 ~~~ foo(); import { foo } from 'my_module'; ;不会报错,import导入早于foo的调用 ~~~ 5. import语句会执行先加载的模块,因此可以使用下面的写法,仅仅执行lodash模块,不输入任何值 ~~~ import 'lodash'; ~~~ ## 5 模块的整体加载 1. 可以使用星号(*)指定一个对象,所有输出值都加载再者对象上面 ~~~ // circle.js export function area(radius) { return Math.PI * radius * radius; } export function circumference(radius) { return 2 * Math.PI * radius; } // main.js import { area, circumference } from './circle'; console.log('圆面积:' + area(4)); console.log('圆周长:' + circumference(14)); // 或者 import * as circle from './circle'; console.log('圆面积:' + circle.area(4)); console.log('圆周长:' + circle.circumference(14)); ~~~ ## 6 export default命令 1. 使用import命令,用户需要知道加载的变量名或函数命令,否则无法加载。为了提供方便,可以直接输出匿名函数,在导入时指定名称 ~~~ // export-default.js export default function () { console.log('foo'); } // import-default.js import customName from './export-default'; customName(); // 'foo' ~~~ 2. 可以使用任意名称指向export-default.js输出的方法,就不需要知道原模块输出的函数名。需要注意的是,import命令后面,不可以使用大括号,也可以使用在非匿名函数前 ~~~ // export-default.js export default function foo() { console.log('foo'); } // 或者写成 function foo() { console.log('foo'); } export default foo; ~~~ 3. 对比默认输出和正常输出 ~~~ // 输出 export default function crc32() { // ... } // 输入 import crc32 from 'crc32'; // 输出 export function crc32() { // ... }; // 输入 import {crc32} from 'crc32'; ~~~ 第一组使用export default时,对应import语句不需要使用大括号, export default命令用于指定模块的默认输出。一个模块只能有一个默认输出,因此export default命令只能使用一次。所以import命名后面不用加大括号,只能导出一个方法。 第二组不使用export default时,对应import语句需要使用大括号 4. 本质上export default输出一个叫做default的变量或方法,允许任意命名。其后不能跟变量声明语句 ~~~ // modules.js function add(x, y) { return x * y; }; export {add as default}; // 等同于 // export default add; // app.js import { default as xxx } from 'modules'; // 等同于 // import xxx from 'modules'; // 正确 export var a = 1; // 正确 var a = 1; export default a; // 错误 export default var a = 1; ~~~ 5. 如果要输出默认的值,只需要在export default输出指定值,也可以用来输出类 ~~~ export default 42; // MyClass.js export default class { ... } // main.js import MyClass from 'MyClass' let o = new MyClass(); ~~~ ## 6 模块的继承 ## 7 模块的循环加载 ## 8 参考 [ES6语法-Module](http://es6.ruanyifeng.com/#docs/module)