Skip to content

Latest commit

 

History

History
179 lines (134 loc) · 4.28 KB

15.module.md

File metadata and controls

179 lines (134 loc) · 4.28 KB

目录

  • 概述
  • 使用方法和注意点

1、概述

一直以来 javascript 的模块化要么使用 commonJS ,要么使用 AMD ,在 ES6 中开始支持模块化了,关键字主要有 import (导入)和 export (导出)。最近一段时间一直在思考 ES6 中的模块化与我们正常使用的 AMD ( 如 requireJS ),以及 commomJS (如 nodeJS )有何不同。在搜索了相关的资料后,发现 ES6 模块化中有些地方很值得注意。

2、使用方法和注意点

2.1 ES6模块是静态加载

ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。 CommonJSAMD 模块,都只能在运行时确定这些东西。

importexport 命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错。这是因为处于条件代码块之中,就没法做静态优化了,违背了 ES6 模块的设计初衷。以下的写法会报错

// 报错
if (x === 1) {
	import { foo } from 'module1';
} else {
	import { foo } from 'module2';
}

// 报错
function foo() {
	export default 'bar' // SyntaxError
}
foo()

2.2 import

2.2.1 由于 import 是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。
// 报错
import { 'f' + 'oo' } from 'my_module';

// 报错
let module = 'my_module';
import { foo } from module;

// 报错
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}

上面三种写法都会报错,因为它们用到了表达式、变量和 if 结构。在静态分析阶段,这些语法都是没法得到值的。

2.2.2 import 语句会执行所加载的模块.如果多次重复执行同一句 import 语句,那么只会执行一次,而不会执行多次。
2.2.3 模块的整体加载
// circle.js
export function area(radius) {
  return Math.PI * radius * radius;
}
export function circumference(radius) {
  return 2 * Math.PI * radius;
}

// main.js
import * as circle from './circle';
console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));

注意,模块整体加载所在的那个对象(上例是 circle ),应该是可以静态分析的,所以不允许运行时改变。下面的写法都是不允许的。

//main.js
import * as circle from './circle';
// 下面两行都是不允许的
circle.foo = 'hello';
circle.area = function () {};

2.3 export

2.3.1 export 命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 报错
export 1;

// 报错
var m = 1;
export m;

上面两种写法都会报错,因为没有提供对外的接口。第一种写法直接输出1,第二种写法通过变量m,还是直接输出1。1只是一个值,不是接口。正确的写法是下面这样。

// 写法一
export var m = 1;

// 写法二
var m = 1;
export {m};

// 写法三
var n = 1;
export {n as m};

上面三种写法都是正确的,规定了对外的接口m。其他脚本可以通过这个接口,取到值1。它们的实质是,在接口名与模块内部变量之间,建立了一一对应的关系。

2.3.2 export 语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。这一点与 CommonJS 规范完全不同。 CommonJS 模块输出的是值的缓存,不存在动态更新。

2.4 export 和 import 使用的例子

2.4.1 export {} + import {}
// jq.js
function myfun () {
	console.log('excuted');
}
export {
	myfun
}

引入方式:

import {myfun} from 'js/jq';
//执行
myfun();
2.4.2 export {} + import * as xxx
// jq.js
function myfun () {
	console.log('excuted');
}
export {
	myfun
}

引入方式:

import * as fn from 'js/jq';
//执行
fn.myfun();
2.4.3 import default + export xxx
// jq.js
function myfun () {
	console.log('excuted');
}
export default {
	myfun
}

引入方式:

import fn from 'js/jq';
//执行
fn.myfun();

参考资料

ECMAScript 6 入门-Module 的语法