Appearance
JavaScript 模块
Function
单纯的使用函数去封装一段特定的代码,会污染所在作用域。 比如我想写一个模块,一个模块又包含很多 function
, 这些 function
实际上只有我写的这个模块会调用。但是他们会暴露在全局作用域中,从而导致了全局作用域被污染。
于是人们想到了通过立即执行函数去创建一个作用域,从而不污染全局作用域,从外仅仅暴露一个模块名称即可。
特点如下:
- 通过立即执行的工厂函数创建一个模块
- 引用其他依赖需要通过
HTML
的script
标签导入的全局变量名 - 依赖关系依赖于
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 新增的,提供了 import
和 from
两个新关键字。
特点如下:
- 通过
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()