最近发现自己基础知识还差的远,很多东西知其然不知其所以然。现在很多项目都可以借助现成的工具来实现,所以真的是越来越少关注了。
但是,基础知识是一个工程师的必备素养,也是你提高的基石,所以我就从一些简单的问题开始做一个系列的记录吧。现在从模块化编程开始吧。
以前:
CommonJS(服务器) 和 AMD(浏览器)规范各自实现了运行时加载模块的方法(没办法在编译时做“静态优化”)。
let { stat, exists, readFile } = require('fs'); let _fs = require('fs'); let stat = _fs.stat; let exists = _fs.exists; let readfile = _fs.readfile;
|
现在:
ES6:一个模块就是一个文件,export/import
命令可以出现在模块的任何位置,只要处于模块顶层就可以。
通过import和export
实现静态加载(编译时加载),服务端和浏览器通用。
import { stat, exists, readFile } from 'fs';
|
export:如果你希望外部能够读取模块内部的某个变量,就必须使用export
关键字输出该变量
var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year};
|
还可以输出函数和class
类:
export function multiply(x, y) { return x * y; };
|
还可以改个名字输出:
function v1() { ... } function v2() { ... } export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion };
|
需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
CommonJS 模块输出的是值的缓存,不存在动态更新。
import:加载模块
import {firstName, lastName, year} from './profile'; function setName(element) { element.textContent = firstName + ' ' + lastName; }
|
可以改名字:
import { lastName as surname } from './profile';
|
注意,import
命令具有提升效果,会提升到整个模块的头部,首先执行。import
命令是编译阶段执行的,在代码运行之前。
由于import
是静态执行,所以不能使用表达式和变量。
会执行加载的模块:
整体加载所有的模块:
import * as circle from './circle';
|
export default:为模块指定默认输出,引用的时候不用知道输出的到底是什么,可以指定任意名字。
需要注意的是,这时import命令后面,不使用大括号。一个模块只能有一个默认输出。
export default function () { console.log('foo'); } import customName from './export-default'; customName();
|
同时引用默认模块和其他模块:
export default function (obj) { } export function each(obj, iterator, context) { } export { each as forEach }; import _, { each, each as forEach } from 'lodash';
|
ES6模块加载CommonJS模块:
module.exports = { foo: 'hello', bar: 'world' }; export default { foo: 'hello', bar: 'world' };
|
import baz from './a'; import {default as baz} from './a'; import * as baz from './a';
|
CommonJS加载ES6模块:通过import()函数
let foo = { bar: 'my-default' }; export default foo; foo = null;
|
const es_namespace = await import('./es'); console.log(es_namespace.default);
|
参考
感谢阮一峰老师的ES6入门教程。