AboutFE
AboutFE copied to clipboard
50、模块化发展历程、IIFE、AMD、CMD、CommonJS、UMD、ES Modules
模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。
IIFE: 使用自执行函数来编写模块化,特点:在一个单独的函数作用域中执行代码,避免变量冲突。
(function(){
return {
data:[]
}
})()
AMD: 使用requireJS 来编写模块化,特点:依赖必须提前声明好。
define('./index.js',function(code){
// code 就是index.js 返回的内容
})
CMD: 使用seaJS 来编写模块化,特点:支持动态引入依赖文件。
define(function(require, exports, module) {
var indexCode = require('./index.js');
});
CommonJS: nodejs 中自带的模块化。
var fs = require('fs');
UMD:兼容AMD,CommonJS 模块化语法。
webpack(require.ensure):webpack 2.x 版本中的代码分割。
ES Modules: ES6 引入的模块化,支持import 来引入另一个 js 。
import a from 'a';
ES Modules与common.js区别
- 输出值
- es6输出的是一个值的引用( ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。)
- common 输出的是一个值的拷贝(模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。)
- 加载方式
- common 运行时加载 (因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成)
- es6 编译时输出接口 (ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。)
AMD,CMD用的不多,主要讲一下CommonJS和ESModule
模块的特性
- 为创建一个内部作用域而调用了一个包装函数。
- 包装函数的返回值至少包含一个对内部函数的引用,这样才会创建涵盖整个包装函数内部作用域的闭包。
CommonJS
特点: require
、module.exports
、exports
CommonJS 一般用在服务端或者Node用来同步加载模块,它对于模块的依赖发生在代码运行阶段,不适合在浏览器端做异步加载。
exports
实际上是一个对module.exports
的引用:
exports.add = function add () {/* 方法 */}
// 等同于
module.exports.add = function add () {/* 方法 */}
但注意,不能给exports
赋值,否则会断开与module.exports
的连接。
ES6 Module
特点: import
、export
ES6模块化不是对象,import
会在JavaScript引擎静态分析,在编译时就引入模块代码,而并非在代码运行时加载,因此也不适合异步加载。
在HTML中如果要引入模块需要使用
<script type="module" src="./module.js"></script>
ESModule的优势:
- 死代码检测和排除。我们可以用静态分析工具检测出哪些模块没有被调用过。比如,在引入工具类库时,工程中往往只用到了其中一部分组件或接口,但有可能会将其代码完整地加载进来。未被调用到的模块代码永远不会被执行,也就成为了死代码。通过静态分析可以在打包时去掉这些未曾使用过的模块,以减小打包资源体积。
- 模块变量类型检查。JavaScript属于动态类型语言,不会在代码执行前检查类型错误(比如对一个字符串类型的值进行函数调用)。ES6 Module的静态模块结构有助于确保模块之间传递的值或接口类型是正确的。
- 编译器优化。在CommonJS等动态模块系统中,无论采用哪种方式,本质上导入的都是一个对象,而ES6 Module支持直接导入变量,减少了引用层级,程序效率更高。
二者的差异
CommonJS模块引用后是一个值的拷贝,而ESModule引用后是一个值的动态映射,并且这个映射是只读的。
- CommonJS 模块输出的是值的拷贝,一旦输出之后,无论模块内部怎么变化,都无法影响之前的引用。
- ESModule 是引擎会在遇到
import
后生成一个引用链接,在脚本真正执行时才会根据这个引用链接去模块里面取值,模块内部的原始值变了import
加载的模块也会变。
CommonJS运行时加载,ESModule编译阶段引用。
- CommonJS在引入时是加载整个模块,生成一个对象,然后再从这个生成的对象上读取方法和属性。
- ESModule 不是对象,而是通过
export
暴露出要输出的代码块,在import
时使用静态命令的方法引用指定的输出代码块,并在import
语句处执行这个要输出的代码,而不是直接加载整个模块。
Originally posted by @Reaper622 in https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/28#issuecomment-562807639
https://www.yuque.com/docs/share/9f219af8-12a5-4441-978f-201ef03987ab?