ES6-Module
前言
许多年前,我们引入代码,是直接用 script src引入, 或者自己写一个 loadScript。
用script src方式的话,当项目中js文件多了,页面上会有很多script标签,抛开性能暂且不说,本身代码就非常丑陋,而且很不好维护,尤其是当 js 文件有依赖关系时,更加难以处理。
为了解决这一痛点,处理好 js 的加载和依赖关系,并推进 js 模块化开发, 于是就有了 用于浏览器端的 CMD, AMD 等规范, 用于服务端(比如nodejs)的 CommonJs规范, 以及最终的标准 ES6 Module 规范。先大致了解一下这几个东东。
CMD: Common Module Definition - 公共模块定义, 是玉伯先生的SeaJS 在推广过程中对模块定义的规范化产出。
AMD:Asynchromous Module Definition - 异步模块定义 是RequireJS在推广过程中对模块定义的规范化产出。
CommonJs规范:服务端规范,文件即模块。用 module.exports 导出模块,require 引入文件/模块。
ES6 Module:ES6 模块标准。
语法以及运用
CMD、 AMD 、CommonJs不作过多描述。想了解的童鞋请上网搜索。这里主要记录 ES6 Module。
ES6 Module 自动采用严格模式,不管你有木有在代码中加上 'use strict'。
export 导出变量, import 导入变量。搞过后端语言的童鞋,应该很熟悉吧。
export 的用法
//export 可以导出 变量,对象, 函数,类。
export const root = 'linux'; let username = 'captain'; let password = 'pwd'; export { username, password } export const add = (x) => x + x; export class fun{}
注意一点, export 命令规定的是对外的接口,所以要保证接口名必须与模块内部变量建立一一对应的关系。
这句话是什么意思,就是不能定义好变量,就直接把变量 export。因为这时候,export 出去的其实是变量的值。
所以要么在定义时就 export, 要么在文件末尾 export 一个对象,对象里是要导出的变量,成键值对关系。
//报错 export 1; //正确 const t = 1; export { t } //报错 const test = () => {} export test; //正确 export test = () => {} export { test }
有时候,我们想给导出的变量换个名字, 这个时候就可以用 as 关键字了。重命名后,一个变量可以导出多次。
语法为: 变量名 as 新变量名
const f1 = () => {} const f2 = () => {} export { f1 as fun1, f2 as fun2,
f2 as alsoFun2 }
最后: export
语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
import 的用法
使用 export 命令定义了模块的对外接口以后, 就可以用 import 加载这个模块了。同样的,import 也有 as 关键字, 也是用于重命名。
以下是 import 的常用语法
import { funName } from 'file.js'; import { funName as newFunName } from 'file.js';
import * as newModuleName from 'file.js';
//如果模块用的是 export default
import defaultName from 'file.js';
注意一点: import命令具有提升效果,会提升到整个模块的头部,首先执行。
export default 的用法
export default 用法模块的默认输出。一个模块只能有一个默认输出,因此 export default 命令只能使用一次。
本质上,export default 就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字。
因为 export default 命令的本质是将后面的值,赋给default变量,所以也可以直接 export default 一个变量。
这个和 export 有些区别,直接 export 一个变量是会报错的。
export default function () { console.log('export default'); }
export default function add() { return x + x }
注意一点: 正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句, 比如 var, let, const 等。
模块的继承
其实也就是 export 和 import 的复合写法。
注意一点:如果是直接将 继承 的方法 export 出去,当前模块是无法调用继承的方法的。这时候如果需要使用继承的方法,可以分开写,先 import 再 export。
//假如以及有一个 add 模块 export const add = (x) => x + x; export const add2 = (y) => y + y + y; //现在我们需要新增一个 math 模块,继承add模块,并导出 export * from 'add.js'; export const mult = (x) => x * x; //或者我们只需要继承 add 方法,不要 add2 方法。 export { add as addNewName } from 'add.js'; export const mult = (x) => x * x;
//以下是分开的写法
import { add } from 'add.js';
export add;
export const mult = (x) => x * x;
模块按需加载
import( url ) 可以实现按需加载,或条件加载。 它返回一个 promise 对象。单页面应用在配置 route 时大都需要使用 import 按需加载。
总结:
export 命令规定的是对外的接口,所以要保证接口名必须与模块内部变量建立一一对应的关系。
export 不能直接导出一个变量或一个值, export default 可以。不过 export defult 后面不能有字面量声明语句, 而 export 可以。
模块可以继承。继承时, export * 命令会忽略模块的 default 方法。