JavaScript 模块


模块化背景

CommonJS AMD UMD

什么是模块?

如何加载和使用模块? 模块之间通过export 和 import相互使用不同模块之间的功能。 export 将当前模块的变量导出提供给其他模块使用 import 允许从其他模块导入功能

核心模块功能

始终使用严格模式 模块级别作用域 模块代码仅仅在第一次导入时评估 import.meta 当前模块的信息 在模块中this为“undefined” 模块脚本被推迟 async和defer 外部脚本 不允许使用裸模块

import 和 export 语法

导出变量、函数、类

// 导出一个数组
export let months = ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

// 导出一个常量
export const MODULES_BECAME_STANDARD_YEAR = 2015;

// 导出一个类
export class User {
  constructor(name) {
    this.name = name;
  }
}
// 导出一个函数声明
export function sayHi(){
	alert(`Hello, ${user}!`);
}

导出一组变量


let months = ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

// 导出一个常量
const MODULES_BECAME_STANDARD_YEAR = 2015;

// 导出一个类
class User {
  constructor(name) {
    this.name = name;
  }
}
// 导出一个函数声明
export {moths,User, MODULES_BECAME_STANDARD_YEAR}

导入一组变量

// 📁 main.js
import {sayHi, sayBye} from './say.js';

sayHi('John'); // Hello, John!
sayBye('John'); // Bye, John!

命名空间导入

import * as say from './say.js';

say.sayHi('John');
say.sayBye('John');

别名导入和导出

// 📁 main.js
import {sayHi as hi, sayBye as bye} from './say.js';

hi('John'); // Hello, John!
bye('John'); // Bye, John!
export {sayHi as hi, sayBye as bye};


导入别名

import * as say from './say.js';

say.hi('John'); // Hello, John!
say.bye('John'); // Bye, John!

导出默认值

export default class User { // just add "default"
  constructor(name) {
    this.name = name;
  }
}

导入默认值


import User from './user.js'; // not {User}, just User

new User('John');

重命名默认导出


import {default as User, sayHi} from './user.js';

new User('John');

重新导出 export … from …

export {sayHi} from './say.js'; // re-export sayHi
export {default as User} from './user.js';

动态导入

在了解动态导入之前,先了解什么是静态导入。

什么是静态导入?

前面所述通过import在顶层导入的模块都属于静态导入。

静态导入有什么问题?

初始加载时间长 只能在顶层导入,无法在条件表达式和控制运算符里面使用。 无法按需导入

如何使用动态导入?

import()表达式,import()表达式返回一个promise,该promise成功时返回一个导出模块的对象。并且没有使用位置限制。

import表达式的用法

常规用法

import(modulePath)
  .then(obj => <module object>)
  .catch(err => <loading error, e.g. if no such module>)

import()表达式和await运算符一起使用

let {hi, bye} = await import('./say.js');

总结

浏览器兼容性