模块化之前存在的问题
- 全局变量污染:各个文件的变量都是挂载到window对象上,污染全局变量。
- 变量重名:不同文件中的变量如果重名,后面的会覆盖前面的,造成程序运行错误。
- 文件依赖顺序:多个文件之间存在依赖关系,需要保证一定加载顺序问题严重。
模块化定义
把一个复杂的东西分解成多个甚至多层次的组成部分,以一种良好的机制管理起来,就可以认为是模块化。而对于软件开发来说,函数(过程)就是最常见也是最基本的模块之一。
用乐高积木来比喻模块化,每个积木都是固定的颜色、大小和形状,想要组合积木必须使用积木凸起和凹陷的部分进行连接,最后多个积木累积成你想要的形状。
模块化其实是一种规范,一种约束,这种约束会大大提升开发效率。将每个js文件看作是一个模块,每个模块通过固定的方式引入,并且通过固定的方式向外暴露指定的内容。 按照js模块化的设想,一个个模块按照其依赖关系组合,最终插入到主程序中。
模块化规范的发展过程
无模块化-->CommonJS规范(基于Node)-->AMD规范(RequireJS)-->CMD规范(SeaJS)-->ES6模块化
Module
模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
export & import
基本使用
// 导出
export const a = 5
export const b = 'ES6'
export const sum = (x, y) => x + y
export const obj = {
name: 'lee'
}
// 导入
import {a,b,sum,obj} from './Module text'
逐个导出太麻烦?
定义了那么多变量,如果都逐个使用export导出,未免也太麻烦了吧
那么就先定义,后一次性导出吧
// 导出
const a = 5
const b = 'ES6'
const sum = (x, y) => x + y
const obj = {
name: 'lee'
}
class People {
constructor(name) {
this.name = name
}
sayName() {
console.log(this.name);
}
}
export { a, b, sum, obj, People }
// 导入
import { a, b, sum, obj, People } from './Module text'
console.log(a, b);
console.log(sum(1, 2));
console.log(obj);
let p = new People('lee')
p.sayName();
as - 起个别名
导入的时候如果我不想要导出时候的变量名,想换一个变量名怎么办?
使用as给原来的名字起个别名,同时原来的名字也就不能再被使用了
import { a as init} from './Module text'
console.log(a, b);
注意导入的时候,一旦使用as给导入的变量起了个别名,那么之前的名字就不能使用了,否则会报错
export default
默认导出
export default 和 export的区别
- 通过export导出的时候,import导入的变量要放到括号
{}中,导入、导出的变量名必须一致(除了使用as添加别名)- 通过export default 默认导出,导入的时候名字可以随便取
// 导出
const a = 5
export default a
// 导入
import renameA from './Module text'
一个模块中只能有一个export default
一个模块中只能有一个export default关键字,否则就会报错
// 导出
const a = 5
export default a
const b = 6
export default b
当然把变量声明和export default 放在一行也是一种错误的写法
export default const a = 5
如果同时拥有export和export default 呢?
- 使用export导出的变量,在导入的时候变量名要和导入的时候一致,同时必须放到大括号中
- 使用export default 导出的变量名字随便取,同时不用放到大括号中
结合起来写就可以了
// 导出
export const str = 'lee'
const sum = (x,y) => x + y
export default sum
// 导入
import sum2,{str} from './Module text'
把一堆东西,通过export default 导出呢?
那么最后导出的结果就是将这些属性全部放到一个空对象上
// 导出
const a = 5
const b = 'ES6'
const sum = (x, y) => x + y
const obj = {
name: 'lee'
}
class People {
constructor(name) {
this.name = name
}
sayName() {
console.log(this.name);
}
}
export default { a, b, sum, obj, People }
// 导入
import foo from './Module text'
console.log(foo);
导入的时候变量名随便取,导出后得到的就是个拥有很多属性的对象,我们也可以通过es6的解构赋值快速取出这些属性对应的值
import * 导入所有
得到的结果是Module对象,属性都放在Module.default上
import * as foo from './Module text'
console.log(foo);