详解ES6 模块化

本秂侑毒 提交于 2020-01-22 03:21:16

详解ES6 模块化

本文我们学习ES6模块化,如何从模块中导出变量、函数、类并在其他模块中重用。
ES6 模块即为在严格模式下执行的JavaScript文件。意味着模块中声明的变量和函数不会自动增加至全局作用域中。

1. 浏览器中执行模块

首先创建新文件message.js并增加下列代码:

export let message = 'ES6 Modules';

在es6中message.js是一个模块,包含message变量。export语句暴露message变量给其他模块。

其次,创建新的文件app.js使用message.js模块。app.js模块创建h1元素并添加至html页中。import语句从message.js模块中导入message变量。

import { message } from './message.js'
 
const h1 = document.createElement('h1');
h1.textContent = message
 
document.body.appendChild(h1)

第三步,创建新的html页面文件使用app.js模块:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>ES6 Modules</title>
</head>
<body>
<script type="module" src="./app.js"></script>
</body>
</html>

注意在script标签中加载type=“module”,如果在浏览器中打开该页面,下面信息:

ES6 Modules

下面我们详细讲解导入和导出语句。

2.Es6模块化

2.1 导出

要导出变量、函数或类,需要在其前面加export关键字:

// log.js
export let message = 'Hi';
 
export function getMessage() {
  return message;
}
 
export function setMessage(msg) {
  message = msg;
}
 
export class Logger {
}

log.js模块中有一个变量、两个函数和一个类,我们使用export关键字导出模块中所有标识符。
注意export关键字需要函数或类有名称,不能导出匿名函数或类。

JavaScript也支持先定义变量、函数或类,再导出:

// foo.js
function foo() {
   console.log('foo');
}
 
function bar() {
  console.log('bar');
}
export foo;

上例首先定义for函数然后导出。因为没有导出bar函数,其他模块不能访问该,对其他模块来说其是私有的不能访问。

2.2 导入

一旦在模块中使用export导出外部能访问的变量、函数或类,其他模块使用import关键字进行引入,语法如下:

import { what, ever } from './other_module.js';
  • 使用花括号指定导入内容,称为绑定
  • 指定从哪个模块导入绑定

注意当从模块中导入绑定时,绑定行为与const关键字定义类似。意味着不能其他标识符与之同名或修改绑定的值。
请看示例:

// greeting.js
export let message = 'Hi';
 
export function setMessage(msg) {
  message = msg;
}

当导入message变量和setMessage函数,可以使用setMessa函数去改变message的值:

// app.js
import {message, setMessage } from './greeting.js';
console.log(message); // 'Hi'
 
setMessage('Hello');
console.log(message); // 'Hello' 

但不能直接改变变量message的值,下面语句编译错误:

1
message = 'Hallo'; // error

实际你调用setMessage函数时,JavaScript回到greeting.js模块中执行代码修改message变量值,其他改变自动反应至导入的绑定变量message。

在app.js中的绑定变量message是局部变量,因此在两个模块中的message并不相同。

  • 导入单个绑定

假如模块中有foo变量如下:

// foo.js
export foo = 10;

另一个模块能使用foo变量:

// app.js
import { foo } from './foo.js';
console.log(foo); // 10;

然而,你不能改变foo的值,如果修改则编译错误:

foo = 20; // throws an error
  • 导入多个绑定

定义cal.js模块:

// cal.js
export let a = 10,
           b = 20,
           result = 0;
 
export function sum() {
  result = a + b;
  return result;
}
 
export function multiply() {
  result = a * b;
  return result;
}

你想从cal.js模块中导入这些绑定,可以显示列举:

import {a, b, result, sum, multiply } from './cal.js';
sum();
console.log(result); // 30
 
multiply();
console.log(result); // 200
  • 导入全部模块作为对象

使用型号可以导入模块所有内容作为单个对象:

import * as cal from './cal.js';

示例中从cal.js模块中导入所有绑定作为单个对象,则所有绑定作为cal对象属性,访问示例:

cal.a;
cal.b;
cal.sum();

这个导入也称为命名空间导入。
特别需要注意的是import语句即使使用多次仅执行一次,示例:

import { a } from './cal.js';
import { b } from './cal.js';
import {result} from './cal.js';

第一个import语句之后,cal.js语句已执行并加载至内存,后续import语句会重用已载入内容。

2.3. import和export限制

注意import和export语句必须在其他语句和函数的外面。下面语句编译错误:

if( requiredSum ) {
   export sum;
}  

同样下面语句也错误:

function importSum() {
   import {sum} from './cal.js';
}

因为两者都在其他语句之内。

2.4. 别名

JavaScript允许在导入或导出时创建别名。下面math.js模块:

// math.js  
function add( a, b ) {
   return a + b;
}
 
export { add as sum };

在导出时add使用as关键字增加别名为sum。

因此在导入add函数时必须使用sum代替:

import { sum } from './math.js';

在导入时也可以使用as关键字指定别名:

import {sum as total} from './math.js';

2.5. 重新导出绑定

也可以对导入绑定重新导出:

import { sum } from './math.js';
export { sum };

在示例从math.js模块导入sum,然后再重新导出。等价语句为:

export {sum} from './math.js';

在重新导出之前需重新命名绑定可使用as关键字。请看下面示例:

export { sum as add } from './math.js';

也可以导出其他模块所有绑定,使用星号:

export * from './cal.js';

2.6. 无绑定导入

有时你想开发不导出任何内容的模块,举例给内置Array对象增加新的方法:

// array.js
if (!Array.prototype.contain) {
  Array.prototype.contain = function(e) {
    // contain implementation
    // ...
  }
}

现在可以导入该模块,无需任何绑定并使用contain()方法:

import './array.js';
[1,2,3].contain(2); // true

2.7. 缺省导出

模块有仅只有一个缺省导出。缺省导出方便导入使用。模块缺省导出可以使用变量、函数或类,下面是sort.js模块的缺省导出:

// sort.js
export default function(arr) {
  // sorting here
} 

注意无需给函数指定名称,默认使用模块名称作为函数名称。

import sort from sort.js;
sort([2,1,3]);

你看到sort表示表示sort.js模块的缺省函数,我们不能对sort标识符使用{}。

下面修改sort.js模块增加非缺省函数:

// sort.js
export default function(arr) {
  // sorting here
}
export function heapSort(arr) {
  // heapsort
}

导入两个绑定可以使用绑定列表,规则如下:

  • 确定绑定必须在首位
  • 非缺省绑定必须使用花括号
import sort, {heapSort} from './sort.js';
sort([2,1,3]);
heapSort([3,1,2]);

从命名缺省导出可以使用as关键字:

import { default as quicksort, heapSort} from './sort.js';

3. 总结

本文我们学习ES6模块,如何从模块中导出绑定以及在其他模块中引入。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!