本文最后更新于:8 个月前
归纳ES6 Module语法、以及export和import的用法
同时简单介绍了CommonJS的用法,因其在Node.js环境中使用较多,而且可以和ES6 Module混用,所以作为拓展,以示区分
JavaScript进阶(五)ES6模块化语法
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
它自动使用严格模式。模块功能主要由两个命令构成:export
和import
。export
命令用于规定模块的对外接口,import
命令用于输入其他模块提供的功能。
一、export命令
export常见用法示例
1 2 3 4 5
| var firstName = 'Michael'; var lastName = 'Jackson'; function getName(){return firstName + lastName}
export { firstName, lastName, getName };
|
1.1 as关键字重命名
使用 as关键字 可以在导出变量时,对其重命名
1 2 3 4 5 6 7 8
| function v1() { ... } function v2() { ... }
export { v1 as streamV1, v2 as streamV2, v2 as streamLatestVersion };
|
对同一个变量,可以定义多个不同的名字(变量名字本质上是对外的接口)
1.2 export需要注意的问题
第一,export必须与模块内部的变量建立一一对应关系。示例如下:
错误示例:
1 2 3 4 5 6 7 8 9
| export 1
var m=1 export m
function f(){} export f
|
正确写法如下:
1 2 3 4 5 6 7 8 9 10 11 12
| export var m=1
var m=1 export {m}
export function f(){}
function f(){} export {f}
|
第二,export命令必须声明在模块顶层,如果export处于块级作用域内,会报错
1 2 3 4
| var obj = { name:'timegogo' } export {obj}
|
1 2 3 4 5 6 7
| var obj = { name:'timegogo' } function f(){ export {obj} } f()
|
1.3 export default
使用export
命令导出的模块,必须预先知道里面的变量名才能进行import(或者直接import *
)。但是用户并不一定知道模块里面的变量名,为了解决这个麻烦,可以用export default
命令。
一个模块只能有一个export default
语句!
使用export default
导出的变量,在其它模块中import导入时,可以指定为任意名字(而无须知道变量原本的名字),同时不需要用大括号包裹
本质上,export default
就是输出一个叫做default
的变量或方法,然后系统允许你为它取任意名字。
1 2 3 4 5 6
| function add(x,y){return x+y} export default add
import fn from 'module.js'
|
实质上等于下面的代码
1 2 3 4 5 6
| function add(x,y){return x+y} export {add as default}
import {default as fn} from 'module.js'
|
正是因为export default
命令其实只是输出一个叫做default
的变量,所以export default
后面不能跟变量声明语句。
1 2 3 4 5 6 7 8
| export var a=1 export default var a=1
var a=1 export default a
export default 1 export 1
|
export default命令可以和 export命令 一起使用。export default
最多可以用一次,而export
命令可以用多次
1 2 3 4 5 6 7
| export default function(obj){} export function each(){} export {each as forEach}
import _,{each,forEach} from 'module.js'
|
二、import命令
使用export
命令定义了模块的对外接口以后,其他 JS 文件就可以通过import
命令加载这个模块。
import
命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js
)对外接口的名称相同
1 2 3 4 5 6 7
| export var firstName='Q' var lastName = 'A' export {lastName}
import {firstName,lastName} from 'module.js'
|
import导入默认接口时,可以不用大括号包裹,而且可以任意指定变量名
1 2 3 4 5 6
| function bar(){} export default bar
import fn from 'module.js'
|
2.1 as关键字重命名
使用 as关键字 可以在导入变量时,对其重命名
1 2 3 4 5
| export var lastName = 'A'
import {lastName as surname} from 'module.js'
|
2.2 import导入的变量是只读的
import导入的变量本质上是输入接口,所以不允许在加载模块的脚本里改写接口。但是如果导入的是一个对象,那么修改对象内部的属性是可以的
1 2 3 4 5 6 7 8 9 10 11
| var obj = { name:'timegogo' } export default obj
import person from 'module.js' person = {} person.name = 'QA'
|
2.3 import不能使用表达式和变量
因为import是静态执行,所以不能使用表达式和变量。import会提升到整个模块的头部,在所有代码之前执行
1 2 3 4 5 6 7 8 9 10
| import {'f'+'oo'} from 'module.js'
var module = 'module.js' import {fn} from module
if(x==1){ import {foo} from 'module1.js' }else{ import {foo} from 'module2.js' }
|
2.4 import整体导入
使用*
可以表示导入模块内所有接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function f1(){console.log(1)} function f2(){console.log(2)} export {f1,f2}
import * as Fn from 'module.js' Fn.f1() Fn.f2() Fn.f1 = ()=>{}
import * from 'module.js' f1()
|
2.5 import 和 模块代码的执行顺序
在使用import的脚本中,import最先被执行,不管import语法所处的位置如何。
使用import语句后,会执行对应模块中所有代码
1 2 3 4 5 6 7 8 9 10 11
| console.log(1) export function fn(){} console.log(2)
console.log(3) import {fn} from 'module.js' console.log(4)
|
三、export+import组合使用
先来看一个场景:我们先是在脚本中导入了变量,然后又把这些变量原封不动地导出
1 2 3
| import {foo,bar} from 'module.js' export {boo,bar}
|
上面的代码可以改写为:
1
| export {foo,bar} from 'module.js'
|
这就是export和import的组合使用
3.1 重命名导出
1
| export {foo as myFoo} from 'module.js'
|
3.2 整体导入导出
1
| export * from 'module.js'
|
3.2 默认接口导出
1 2 3 4 5 6 7 8
| export {default} from 'module.js'
export {default as es6} from 'module.js'
export {es6 as default} from 'module.js'
|
四、拓展:CommonJS
CommonJS 是一个项目,其目标是为 JavaScript 在网页浏览器之外创建模块约定。创建这个项目的主要原因是当时缺乏普遍可接受形式的 JavaScript 脚本模块单元
CommonJS基于Node.js,离开Node.js环境无法使用!
我们现在大多使用的是 webpack 进行项目构建打包,因为现在前端开发环境都是在 Node 环境原因,而 npm 的包都是 CommonJS 规范的,所以 webpack 对ES6模块进行扩展 支持 CommonJS,并支持node的导入npm包的规范
4.1 导出方式
第一种,单个导出
1 2 3 4 5 6
| module.exports.age = 1 module.exports.foo = function(){}
exports.a = 'hello'
|
第二种,整体导出
1 2 3 4 5 6 7 8 9 10 11
| module.exports = { age: 1, a: 'hello', foo:function(){} }
var age=1 var a='hello' function foo(){} module.exports = {age,a,foo}
|
4.2 导入方式
1 2 3 4 5 6
| const foo = require('module.js') foo.fn()
const {fn} = require('module.js') fn()
|
参考文章
Module 的语法 - ECMAScript 6入门 (ruanyifeng.com)
前端科普系列-CommonJS:不是前端却革命了前端 - 知乎 (zhihu.com)