CommonJS

遵循规范

  • require 是 AMD规范引入方式
  • import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法

    调用时间

  • require是运行时调用,所以require理论上可以运用在代码的任何地方

  • import是编译时调用,所以必须放在文件开头

    本质

  • require是赋值过程,其实require的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量 , 本质是按值来传递

  • import是解构过程,但是目前所有的引擎都还没有实现import,我们在node中使用babel支持ES6,也仅仅是将ES6转码为ES5再执行,import语法会被转码为require, 按照引用传递

模块化导入衍生问题

简介

通常来说,一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数

CommonJS

NodeJS是CommonJS规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持

CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性

  1. var x = 5;
  2. var addX = function (value) {
  3. return value + x;
  4. };
  5. module.exports.x = x;
  6. module.exports.addX = addX;

AMD

AMD是RequireJS使用的规范,是为了浏览器中的模块加载而实现的。并且AMD是异步加载

循环依赖

那么AMD是如何解决循环依赖的?其实就是强制忽略了,比如有两个模块A,B。当A依赖B,然后B依赖A的时候,B获取到的A是为未定义的状态。而且总是会把依赖的模块执行完成,也就是说B一定会被先执行完成。

CMD

是 SeaJS 在推广过程中对模块定义的规范化产出,它与AMD很类似,不同点在于:AMD推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。

UMD

umd是一种思想,就是一种兼容 commonjs,AMD,CMD 的兼容写法,define.amd / define.cmd / module 等判断当前支持什么方式,
UMD先判断支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。都不行就挂载到 window 全局对象上面去

ES6 Module

ES Module的诞生可以说是真正意义上的解决了前后端模块导入的问题

加载机制

ES6 模块的运行机制与 CommonJS 不一样。ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,import时采用静态命令的形式。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。模块内部引用的变化,会反应在外部。
在import时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”。在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。

循环依赖

ES6 Module其实并不关心有没有循环依赖,他并不需要产生结果,他只需要给你一个引用即可,至于是否能取到值,那么就需要开发者自己来保证了

声明

  1. // math.js
  2. export function add(){}
  3. export default {
  4. add
  5. }
  6. export var name = 'box'

使用

  1. import {add} from './math'
  2. add()