文章目录
一、现阶段的模块化方案
CommonJS
:NodeJS
模块系统具体实现的基石。AMD
:异步模块规范,是RequireJS
在推广过程中对模块定义的规范化产出的,推崇依赖前置,异步加载;CMD
:是SeaJS
在推广过程中对模块定义的规范化产出的,推崇依赖就近,同步加载;UMD
:兼容AMD
和CommonJS
规范的同时,还兼容全局引用的方式;ES6
:ES6
模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量;
其中AMD
和CMD
的语法类似,都是使用define
和require
来进行模块的定义和加载;CommonJS
则使用的是moduel.exports
、exports
和require
来紧密模块的定义和加载。然而从本质上来讲,它们都没有解决根本问题:
- 性能低:浏览器最怕从服务器加载又小又多的文件;
- 模块之间的管理之类的问题;
- 都是JavaScript函数模拟实现的,需要第三方库的支持;
而ES6(ECMAScript2015)
可以说是一个“跨时代”的更新,使得的JavaScript
在原生语言上实现了模块化:export
和import
。ES6
的原生模块功能,它兼顾了规范、语法简约型和异步加载功能,还支持循环依赖。是不是很强大。
二、ES6模块
在ES6
中每一个模块就是一个独立的文件,并且是自动采用严格模式,所以在编写ES6
模块的时候要严格遵守严格模式的一些限制。
在文件中定义的变量、函数、对象外部是无法读取的。ES6
模块的语法主要由两个命令构成:export
和import
。
export
用于对外暴露模块内部的接口和变量;- 通常
import
用于引入其他模块暴露在外的接口。
下面来看看它们的具体用法:
export
的语法(以下定义的模块:mod.js
)
1、定义的同时导出
/*************文件导出************/
// 导出变量
export let a = 20;
export const c = 30;
// 导出函数sum
export function sum(x,y){
return x+y
}
// 导出Person类
exprot class Person{
constructor(name){
this.name = name;
}
say(){
console.log(`我是${this.name}`)
}
}
2、先定义后导出
/*************导出************/
let a = 20;
const c = 30;
export { a,b }
3、另类的导出:export default
/*************导出************/
// 另类的导出:正确的
export default 'aaa';
export语法汇总
/*************导出************/
// 正确语法
export let xxx;
export { xxx, xxxx, ...};
export default 'aaa';
// 错误语法
export xxx;
注意:export
命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系
以上定义了mod.js
模块,下面import
的语法基于mod
模块进行
import的语法
1、全部导入
/*************导入************/
// .js可有可无,但是前面的./要加上哦
import * as mod from './mod.js'
console.log(mod.a, mod.b) // 20 30
console.log(mod.sum(mod.a, mod.b)) // 50
let p = new mod.Person('smallteem');
p.say(); //我是smallteem
2、局部导入:只导入sum方法
/*************导入************/
// { sum } 这里使用的是ES6的解构语法哦
import { sum } from './mod.js'
console.log(sum(14,16)) // 30
#### 3、导入默认成员:对应export default
```javascript
/*************导出************/
export default 'aaa'
/*************导入************/
import a from './mod'
console.log(a) // 'aaa'
4、另类的导入:引入整个模块,不引入内部成员
/*************导入************/
// 引入js
import 'lodash';
// 引入其他资源,需要配合其他的loader使用
// 在vue之后比较常见
import './style.css'
import './logo.png'
5、当做函数使用:返回的是一个promise
/*************mod2文件 导出************/
export let qq = 'abc'
/*************导入************/
import * as mod from './mod'
import('./mod2')
.then(mod2 => {
console.log('mod2加载成功')
console.log(mod2.qq)
},err => {
console.log('mod2加载失败')
})
通常不重要的模块可以使用异步加载,比如广告文件等等
export和import复合写法
如果在一个模块B之中,先输入A,然后要把A中的成员在输出,这时候就需要用到复合写法了:import
语句可以与export
语句写在一起。
/*************模块B导出************/
export { foo, bar } from 'A';
// 可以简单理解为
import { foo, bar } from 'A';
export { foo, bar };
export { es6 as default } from './someModule';
// 等同于
import { es6 } from './someModule';
export default es6;
常用写法汇总
export
export let a=xx;
export const a=xx;
export function xxx(){
};
export class xxx{
}
export {xxx, xxx, xxx, ...};
export default xx;
//从另一个模块导出
export * from './m2';
export {x,x,x,x} from './m2';
export {default} from './m2';
import
import * as mod from "./xxx";
import {a, b, c, ...} from "./xxx";
//引入默认成员
import xxx from './mod';
//模块的代码引入进来,不引入内部成员
import "./1.jpg";
import "./1.css";
//异步引入
let promise=import("./mod1");
以上是es6
模块化的常规用法,尽管es6
模块化这么好用这么强大,尽管es9
都出来了,然而,到目前为止没有一款浏览器直接支持export
和import
语法。所以es6
的模块化还需要搭配babel
转码成浏览器支持的es5
语法。
欢迎关注同步微信公众号:前端小菜的进阶之路