ES6 - Module

138 阅读4分钟

模块化之前存在的问题

  • 全局变量污染:各个文件的变量都是挂载到window对象上,污染全局变量。
  • 变量重名:不同文件中的变量如果重名,后面的会覆盖前面的,造成程序运行错误。
  • 文件依赖顺序:多个文件之间存在依赖关系,需要保证一定加载顺序问题严重。

模块化定义

把一个复杂的东西分解成多个甚至多层次的组成部分,以一种良好的机制管理起来,就可以认为是模块化。而对于软件开发来说,函数(过程)就是最常见也是最基本的模块之一。

用乐高积木来比喻模块化,每个积木都是固定的颜色、大小和形状,想要组合积木必须使用积木凸起和凹陷的部分进行连接,最后多个积木累积成你想要的形状。

模块化其实是一种规范,一种约束,这种约束会大大提升开发效率。将每个js文件看作是一个模块,每个模块通过固定的方式引入,并且通过固定的方式向外暴露指定的内容。 按照js模块化的设想,一个个模块按照其依赖关系组合,最终插入到主程序中。

模块化规范的发展过程

无模块化-->CommonJS规范(基于Node)-->AMD规范(RequireJS)-->CMD规范(SeaJS)-->ES6模块化

Module

模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,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给导入的变量起了个别名,那么之前的名字就不能使用了,否则会报错

image.png

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

image.png

当然把变量声明和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的解构赋值快速取出这些属性对应的值

image.png

import * 导入所有

得到的结果是Module对象,属性都放在Module.default

import * as foo from './Module text'
console.log(foo);

image.png