您现在的位置是:首页 >学无止境 >Module的语法, JS中的 export 和 import网站首页学无止境
Module的语法, JS中的 export 和 import
在ES6之前, 社区制定了一些模块加载方案, 最主要的有CommonJS和AMD两种. 前者用于服务器,后者, 用于浏览器
ES6模块的设计思想是尽量静态化, 使得编译时就能确定模块的依赖关系
ES6模块不是对象, 而是通过export命令显示指定输出的代码,再通过import命令输入.
// ES6模块
import { stat, exists, readFile } from 'fs'
上面代码的实质是从fs模块加载3个方法, 而不加载其他方法. 这种加载成为"编译时加载"或"静态加载', 即ES6可以在编译时就完成模块加载
注意:
在ES6模块中, 顶层的this指向undefined, 不应该在顶层代码中使用this.
export 命令
export 命令用于规定模块的对外接口.
一个模块就是一个独立的文件, 这个文件内部的所有变量,外部无法获取. 如果希望外部能够读取模块内部的某个变量,就必须使用export 关键字输出该变量.
// 下面js文件使用export输出变量
// profile.js
export var firstName = 'wei'
export var lastName = '健力宝'
export var year = '1958'
// 与前一种写法是等价的, 优先考虑这种写法. 可以再脚本尾部一眼看清楚输出哪些变量
var firstName = 'wei'
var lastName = '健力宝'
var year = '1958'
export {
firstName,
lastName,
year
}
// 除了输出变量,还可以输出函数或class
export function multiply(x,y){
return x * y
}
使用as关键字重命名
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
}
// 上面代码使用as关键字重命名了函数v1和v2的对外接口,重命名后v2可以用不同的名字输出
export 命令规定的是对外的接口, 必须与模块内部的变量建立一一对应的关系
// 报错
export 1
// 报错
var m = 1
export m
// 上面两种写法都会报错, 因为没有提供对外的接口.
// 第一种写法直接输出1, 第二种写法通过变量m依然直接输出1. 1只是一个值, 不是接口
// 正确写法
// 写法1
export var m = 1
// 写法2
var m = 1
export { m }
// 写法3
var n = 1
export { n as m}
// 以上三种都是正确的, 规定了对外的接口m. 其他脚本通过这个接口取得值1.
// 它们的实质是, 在接口名与模块内部变量之间建立一一对应.
export 语句输出的接口与其对应的值是动态绑定关系, 通过该接口可以渠道模块内部实时的值
export var foo = 'bar'
setTimeout(() => foo = 'baz', 5000)
// 上面代码输出变量foo, 值为bar, 5000ms之后变成baz.
// 这一点和CommonJS不同, CommonJS模块输出的是值的缓存.
最后, export命令可以出现在模块的任意位置,只要处于模块顶端就可以. 如果处于块级作用域内, 就会报错.
function foo () {
export default 'bar'
}
foo()
// 报错
import 命令
使用export 命令定义了模块的对外接口后, 其他js文件可以通过import命令加载这个模块.
// main.js
import { firstName, lastName, year } from './profile'
// from指定的位置可以是相对位置也可以是绝对位置.
/*
import 命令用于加载profile.js文件 import命令接受一个对象,里面指定要从其他
模块导入的变量名, 大括号中的变量必须与被导入模块对外接口的名称相同.
*/
如果要为输入的变量重新取一个名字,要在import 命令中使用as关键字
import { firstName as surname } from './profile'
import 命令具有提升效果, 会提升整个模块的头部并首先执行
foo()
import { foo } from 'module'
// 不会报错, 因为import的执行早于foo的调用
// 本质是,import命令是在编译阶段执行的,在代码运行之前
模块的整体加载
除了指定加载某个输出值, 还可以整体加载(星号*)来指定一个对象.
// circle.js
export function area(radius) {
return Math.PI * radius * radius
}
export function circumference(radius) {
return 2 * Math.PI * radius
}
// 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 命令
export default 命令为模块指定默认输出
// export-default.js
export default function() { // 默认输出是一个函数
console.log('foo')
}
// import-default.js
import customName from './export-default'
customName() // 输出foo
//上面的import命令可以用任意名称指向export-default输出的方法.这时import不需要大括号
// export default用在非匿名函数也是可以的
export default function foo() {
console.log('foo')
}
import foo from 'foo'
// 对应的import语句不需要使用大括号
// 或者写成
function foo() {
console.log('foo')
}
export foo
// 需要使用大括号
本质上, export default 就是输出一个叫做default的变量或方法, 然后系统允许我们为它取任意名字.
export和import的复合写法
如果在一个模块中先输入后输出同一个模块,import语句可以与export语句写在一起.
export { foo, bar } from 'module'
//等同于
import { foo, bar } from 'module'
export { foo, bar }