Skip to content

JavaScript 模块

Function

单纯的使用函数去封装一段特定的代码,会污染所在作用域。 比如我想写一个模块,一个模块又包含很多 function, 这些 function 实际上只有我写的这个模块会调用。但是他们会暴露在全局作用域中,从而导致了全局作用域被污染。

于是人们想到了通过立即执行函数去创建一个作用域,从而不污染全局作用域,从外仅仅暴露一个模块名称即可。

特点如下:

  • 通过立即执行的工厂函数创建一个模块
  • 引用其他依赖需要通过 HTMLscript 标签导入的全局变量名
  • 依赖关系依赖于 script 的加载顺序

CommonJS

Node.js 所使用的的模块化规范就是 CommonJS。

特点如下:

  • 文件即模块
  • 通过 module.exports 属性导出
  • 通过 require 函数导入
  • 属于同步加载

AMD

全名为 Asynchronous Module Definition。

特点如下:

  • 文件即模块
  • 通过 define 函数定义模块
  • 通过 require 函数导入
  • 属于异步加载

define 函数

define 函数有三种的重载:

typescript
// 'define' function declaration
function define(id: string, deps: string[], factory: (...arg) => () => void)
function define(deps: string[], factory: (...arg) => () => void)
function define(factory: (...arg) => () => void)
// 'define' function implement
function define(id: string, deps: string[], factory: (...arg) => () => void) {
  // 增加判断代码以实现函数重载的功能
  // ...
}

一个使用示例:

javascript
define(['dep1', 'dep2'], function (dep1, dep2) {
    return function () {};
});

require 函数

require 函数保证了指定的所有依赖项被加载完毕后,才调用 callback 函数。

函数签名:

typescript
function require(deps: string[], callback: (...deps) => void) {
  // ...
}

一个使用示例:

javascript
require(['jquery'], function ($) {
  // 现在可以使用 $ 访问 jquery 对象了
})

ESM

ES modules 是 ES2015 新增的,提供了 importfrom 两个新关键字。

特点如下:

  • 通过 export 关键字部分导出或者导出默认
  • 通过 import xxx from './xxx' 导入
  • 通过 import 可以动态导入模块

动态 import 将会返回一个 Promise 对象,这意味着我们可以使用 async/await 语法。

部分导出

javascript
export const nothing = () => {}
export function twoSum(a,b) {
  return a + b
}

部分导入

javascript
import { nothing, twoSum } from 'someModule'

部分导入可以通过 as 关键字取别名。

javascript
import { nothing as noop } from 'someModule'

导出默认

javascript
export default function () {}

导入默认

导入 default 时,名称可以自定义。

javascript
import someModule from 'someModule'

动态 import 时,需要从返回的对象中解构并重命名 default

javascript
async function foo() {
  const { default: someModuleDefault, nothing } = await import('someModule')
}

导入默认时,默认导入的值必须在部分导入的前面。

javascript
import someModule, { nothing } from 'someModule'

导入全部

javascript
import * as myModule from './someModule'
myModule.nothing()