模块相关学习笔记

JS模块系统:

传统方法:
script加载
defer/async 渲染完执行/下载完执行

AMD 、 CMD、 CommonJS、 ES6 Modules

  1. AMD define([‘a’,’b’],function(){}) 提前执行 依赖前置
    CMD define(function(){

    a = require('a')
    

    })
    延迟执行 依赖就近

  2. CommonJs node规则

  3. ES6 Modules
    ES6的模块不是对象,import命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。也正因为这个,使得静态分析成为可能。

  4. ES6 Modules Vs CommonJs

    • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

运行时加载: CommonJS 模块就是对象;即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”。
编译时加载: ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,import时采用静态命令的形式。即在import时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”。

CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

CommonJs总结:生成一个对象,然后再从这个对象上面读取属性。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象。运行时,当遇到require命令,就会全部执行,输出已执行部分,未执行部分不输出(这也是CommonJS解决循环加载的办法)

ES6 模块是动态引用,并且不会缓存值。这样宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能就有机会在JS里实现了。但是由于import是静态执行,所以不能使用表达式、变量、if结构,这些只有在运行时才能得到结果的语法结构,也就无法直接实现条件加载,按需加载等功能。

CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
CommonJS 模块输出的是值的拷贝,ES6 模块输出的是值的引用。