ES6-Module模板


概述

历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 RubyrequirePythonimport,甚至就连 CSS 都有@import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍。

在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。‘

特点

  1. 每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象;

  2. 每一个模块内声明的变量都是局部变量, 不会污染全局作用域;

  3. 模块内部的变量或者函数可以通过export导出;

  4. 一个模块可以导入别的模块;

  5. ES6的模块自动采用严格模式。

功能简介

模块功能主要由两个命令构成 exportimport

  • export 命令用于规定模块的对外接口
  • import 命令用于输入其他模块提供的功能。

export命令

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

1. 最基本的用法

//profile.js
//输出变量:
export var year = 1958; 
//或者写成:
var year = 1958; 
export {year}; (推荐)

//输出函数:
export function f() {};
//或者写成:
function f() {}
export {f};

2. as关键字

重命名对外的接口

function v1(){.....}
function v2(){.....}

export{
    v1 as streamV1,
    v2 as streamV2
}

3. export语句输出的值与对应的值是动态绑定关系,即通过该接口可以取到模块内部实时的值

export var foo="foo";
setTimeout(()=>foo='baz',500);

//输出变量foo,值为bar,500ms后变成baz

4. 错误写法

export命令规定的是对外的接口,实质是在接口名与模块内部变量之间建立了一一对应的关系。

export {foo,baz}

//等价于
export {foo:foo,baz:baz}

针对与上面一点,下面的写法就会导致错误

export 1;

var m=1;
export m;

import命令

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

1. 基本用法

//main.js
import {year} from './profile';

function setName(element){
    element.textContent=year;
}

大括号{}中的变量名必须与被导入模块对外接口的名称相同。

2. as用法

为输入的变量名重新取一个名字

import {year as num} from './profile';

3. from后面的文件位置

  • 可以是相对路径,也可以是绝对路径;
  • .js后缀可以省略;
  • 如果只是模块名,不带有路径,那么必须有配置文件告诉Javascript引擎该模块的位置。

4. import是静态执行

import命令是编译阶段执行的,在代码运行之前。

由于import是静态执行,所以不能使用表岛是和变量,只有在运行时才能得到结果的语法解构。

//报错
import {'fo'+'oo'} from 'my_moudule';

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

模块的整体加载(*)

上面我们代码中涉及到的是指定加载某个输入值,还可以使用整体加载(即型号)来指定一个对象,*所有输出值**都加载在这个对象上。

circle.js文件

export function area(radius) {
  return Math.PI * radius * radius;
}

export function circumference(radius) {
  return 2 * Math.PI * radius;
}

main.js文件

// main.js

import { area, circumference } from './circle';

console.log('圆面积:' + area(4));
console.log('圆周长:' + circumference(14));

上面写法是逐一指定要加载的方法,整体加载的写法如下。


import * as circle from './circle';

console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));

export default 命令

从前面的例子可以看出,使用import命令时用户需要知道所加载的变量名或者函数名,否则无法加载。

为了方便用户,使其不用阅读文档就能加载模块,可以使用export default命令为模块指定默认输出。

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

// import-default.js
import customName from './export-default';
customName(); // 'foo'

上面的import命令可以用任意名称指向文件的输出的方法,这时就不需要知道原模块输出的函数名了。

需要注意的是 这时import命令后面不使用大括号。

export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以import命令后面不用加大括号,因为只可能对应一个方法。

exportimport的复合写法

用于在一个模块之中先输入后输出同一模块。

export { foo, bar } from 'my_module';

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


// 接口改名
export { foo as myFoo } from 'my_module';

// 整体输出
export * from 'my_module';

模块的继承

模块之间也可以继承

// circleplus.js

export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
  return Math.exp(x);
}

注意,export *命令会忽略circle模块的default方法。


文章作者: Rabbit
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Rabbit !
 本篇
ES6-Module模板 ES6-Module模板
概述历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、Python 的import,甚至就连 CSS 都有
2020-03-26
下一篇 
ES6-Promise对象 ES6-Promise对象
Promise是什么? Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。 从语法上说,Promis
2020-03-25 Rabbit
  目录