CommonJS AMD CMD UMD ESM

早期的JavaScript是没有模块的概念,引用第三方包时都是把变量直接绑定在全局环境。这导致变量污染(同名问题)和依赖混乱。

CommonJS 模块规范

Node 应用由模块组成,采用 CommonJS 模块规范。

定义模块

每个模块是个独立的 js 文件。
每个模块中 module 变量代表当前模块,模块的 exports 属性暴露对外的接口
node 为了简化书写,为每一个模块提供了一个 exports 变量指向 module.exports
不能把exports直接指向一个值,这样就相当于切断了 exports 和module.exports 的关系

加载模块

require方法用于加载模块
相当于读入并执行一个js文件,然后返回该模块的 exports 对象

require命令用于加载文件,后缀名默认为.js,可以省去
模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了

CommonJS 特点:

  • 为模块提供单独的作用域
  • 多次引入,只会在第一次执行,之后读取缓存
  • 加载顺序为代码中出现顺序 (同步)

导入机制特点: 对于已导出的变量,不受原文件方法的影响 require的是被exports的值的拷贝
模块可以通过 events 模块发出事件;通过.on方法 监听模块发出的事件

require.resolve() 返回加载的确切文件名
require.main 判断模块是直接执行(值为module本身),还是被调用执行(false)

多次执行模块
  1. 让模块输出一个函数,然后每次 require 这个模块的时候,重新执行一下输出的函数
  2. 清除模块缓存:
// 删除指定模块的缓存
delete require.cache[moduleName];

// 删除所有模块的缓存
Object.keys(require.cache).forEach(function(key) {
  delete require.cache[key];
})

循环加载,再次被加载的模块是不完全执行的,会停在 require 的位置

module 对象

属性 解释
id 模块的识别符,通常是带有绝对路径的模块文件名
filename 模块的文件名,带有绝对路径
loaded 返回一个布尔值,表示模块是否已经完成加载
parent 返回一个对象,表示调用该模块的模块 可以用于判断是否为入口脚本
children 返回一个数组,表示该模块要用到的其他模块
exports 表示模块对外输出的值

模块缓存机制 解决循环依赖问题

AMD规范

允许添加回调函数,异步加载模块 代表 require.js
使用define方法定义模块

 define([module], callback);

第一个参数[module],是一个数组,里面的成员就是要加载的模块;
第二个参数callback,则是加载成功之后的回调函数。

让输出的模块兼容CommonJS规范

define(function (require, exports, module){
  var someModule = require("someModule");
  var anotherModule = require("anotherModule");

  someModule.doTehAwesome();
  anotherModule.doMoarAwesome();

  exports.asplode = function (){
    someModule.doTehAwesome();
    anotherModule.doMoarAwesome();
  };
});

CMD 规范

代表 Sea.js 保证依赖先于文件加载完成
参考博客
define 用来定义模块

define(name?,[depend]?,constructor)

name: 模块标识;
[depend]: 模块的依赖文件数组;
constructor: 构造函数 默认三个参数:require、exports、module
* 当此参数是字符串,对象时,返回的接口就是本身。
* 当为函数时,以这个函数为模块的构造函数,执行此函数,得到向外提供的接口。

if (typeof define === "function" && define.cmd) // 有满足CMD规范的模块加载器存在

require(name) 加载
require.async(name,callback?); 异步加载

ESM (ECMA Script Modules)

详情链接

通过 “模块地图”和“模块记录” 解决循环依赖问题
已经进入过的模块标注为获取中,遇到import语句会去检查这个地图,已经标注为获取中的则不会进入,地图中的每一个节点是一个模块记录,上面有导出变量的内存地址,导入时会做一个连接——即指向同一块内存。

你可能感兴趣的:(#,JavaScript,javascript,前端,开发语言)