欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ECMAScript 6 之Module

程序员文章站 2022-06-13 08:02:00
...

1. 概述

ES6 之前,模块加载方案主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。
ES6 在语言标准的层面上,实现了模块功能,ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

2. 严格模式

ES6中模块自动采用严格模式,关于严格模式,请参考:严格模式

3. export 命令

模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个例子:

// filter.js
// 将0、1 类型 week 转成汉字,如 1001101 转成 “日,三,四,六”
export function weekFormat(str) {
  if (typeof str !== 'string' || str === '') return ''
  const week = str.trim().split('')

  return ['日', '一', '二', '三', '四', '五', '六']
    .filter((item, index) => {
      return week[index] === '1'
    })
    .join(',')
}

上面代码是filter.js文件的内容,定义了一个星期转换函数weekFormat。ES6中,该文件就是一个模块,使用export命令对外输出了函数weekFormat

export命令还有一种写法,如下:

// filter.js
// 将0、1 类型 week 转成汉字,如 1001101 转成 “日,三,四,六”
function weekFormat(str) {
  if (typeof str !== 'string' || str === '') return ''
  const week = str.trim().split('')

  return ['日', '一', '二', '三', '四', '五', '六']
    .filter((item, index) => {
      return week[index] === '1'
    })
    .join(',')
}

export { weekFormat }

上面代码在export命令后面,使用大括号({})指定所要输出的一组变量。这种写法与上面的写法是等价的,但是更加清晰,一目了然。

通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名。

function f1() {
	...
}

export { f1 as getName}

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

export 1; // 报错

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

正确写法如下:

export var m = 1;

// 或
var n = 1;
export { n }

注意:

  • export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。
  • export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错。

4. import 命令

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

// another.js
// 加载模块
import { weekFormat } from './filter.js'

// 使用模块
var util = {
	weekFormat 
}

import命令接受一对大括号({}),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块对外接口的名称相同。

import命令也支持使用as关键字,将输入的变量重命名。

import { weekFormat as a } from './filter.js'

import命令输入的变量都是只读的,因为它的本质是输入接口。即不允许在加载模块的脚本里面,改写接口。

import {  a } from './xxx.js'

a = {} // Syntax Error : 'a' is read-only;

如果a是一个对象,改写a的属性是允许的。

import {  a } from './xxx.js'

a.propertyName = ... 

上面改写对象a的属性是合法的。

import命令具有提升效果,会提升到整个模块的头部,首先执行。

// 使用模块
var a = {
	weekFormat 
}

// 加载模块
import { weekFormat } from './filter.js'

上面例子中,先试用要加载的模块,再通过import命令加载要使用的模块,是可以的,因为import命令具有提升效果。

import命令是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。

// 报错
import { 'week' + 'Format' } from './filter.js'

import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径.js后缀可以省略。如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。
ECMAScript 6 之Module

5. export default 命令

export default命令,为模块指定默认输出。

// a.js
export default function (x, y) {
	return x + y
}

上面例子是一个模块文件a.js,通过export default命令指定了它的默认输出是一个函数。

其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

import add from './a.js'

上面例子的import命令,可以用任意名称指向a.js输出的方法,但是,此时import命令后面,不使用大括号

export default命令也可以用在非匿名函数上。

// b.js
export default function add(x, y) {
	return x + y;
}

//或者
function add(x, y) {
	return x + y;
}

export default add;

上面例子中,函数add的函数名add只在模块内有效,在模块外部是无效的,加载的时候视同匿名函数。

下面是exportexport default命令的简单比较。

// export default 命令
export default function sum() {...}  // 输出

import sum from 'sum' // 输入

// export 命令
export function sum() {...} // 输出

import { sum } from 'sum' // 输入

本质上,export default命令就是输出一个叫做default的变量或方法,下面写法是有效的。

function add(x, y) {
  return x * y;
}

export {add as default};
// 等价于
export default add;

export default命令后面不能跟变量声明语句。

// 正确
export var a = 1;

// 正确
var a = 1;
export default a;

// 错误
export default var a = 1;

上面例子中,最后一种写法不允许,因为export default a的含义是将变量a的值赋给变量default

export default命令的本质是将后面的值,赋给default变量,下面写法是正确的。

// 错误
export 12;

// 正确
export default 12;

6. export 与 import 的复合写法

如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起。

export { foo, bar } from 'my_module';

// 等价于
import { foo, bar } from 'my_module';
export { foo, bar };

模块的接口改名可以采用复合写法。

export { foo as my_foo, bar as my_bar } from 'my_module';

默认接口可以采用复合写法。

export { default }  from 'my_module'

具名接口改为默认接口的写法如下。

export { foo as default } from 'my_module'

// 等价于
import { foo } from 'my_module'
export default foo;

默认接口改为具名接口写法如下:

export { default as foo } from 'my_module'