前端模块化iife、CJS、AMD、UMD、ESM的区别

前端模块化 注:以下所有解释完全依照本人的主观思想,如果有不对的地方,请见谅
说到模块化,不得不先了解一下模块的起源,时间顺序方面不要太在意

  • 初始,只是创建一个js文件,里面定义一些方法、常量等,提供给其他页面使用,这就是一个最简单的模块,那只算是一个功能文件,不是私有的,会污染全局
  • 后来,就把所有的方法放到对象中,通过对象使用这些方法,但是外部可以通过对象更改里面的属性,而且也会污染全局,这个缺点也很不好
  • 然后就出现了命名空间这个东西,命名空间就是说:若全局空间中已有同名对象,则不覆盖该对象,否则创建一个新的命名空间。
    var MYNAMESPACE = MYNAMESPACE || {}; MYNAMESPACE.person = function() { console.log("hello word"); };

    这依然改变不了被修改的命运
模块化的发展 iife(自执行函数) 顾名思义,就是创建的时候就直接执行,然后返回一个参数对象(也可以只返回其他参数),对象中可以有方法,属性等,然后再外部进行调用,不会污染全局,也不会被外部更改
//创建自执行函数 var testUtils = function () { function test(data){ console.log(data) } return { test } }(); //执行自执行函数中的方法 testUtils.test("张三") //执行结果-张三

CJS(CommonJS参考链接https://javascript.ruanyifeng...) 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
CommonJS规范加载模块是同步的,由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用
主要特点:
  • 所有代码都运行在模块作用域,不会污染全局作用域
  • 模块可以多次加载,但是只会在第一次加载的时候执行,然后会缓存一份,后面再引用返回的都是缓存
  • 模块加载的顺序是按照出现的位置来定
  • 因为被输出的是拷贝值,则如果在外部对模块代码就行修改则不会生效
  • 一般用于服务端的规范
AMD(Asynchronous Module Definition)异步模块定义 【前端模块化iife、CJS、AMD、UMD、ESM的区别】跟CJS并称量大通用模块规范,主要用于客户端,因为客户端在加载的时候主要看中加载速度,如果像是CJS那样同步执行的话,在加载一个很大的组件的情况下会相当的耽误时间,所以催生出了AMD客户端的异步规范
AMD规范引用组件方式
require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。
//引入lodash组件并使用 require(['lodash'], function (lo) { lo.isArray([]) });

UMD 他像是一个工厂,为了同时支持CJS和AMD的规范,判断谁的规范支持就使用谁的规范,他的最外层是一个iife
ESM(ES6 Module 参考链接http://caibaojian.com/es6/mod...) ES6实现了模块化功能,在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
主要特点:
  • 完全替代CJS和AMD,淘汰了UMD,命名空间等规范
  • 静态化,编译时加载,使得页面加载速度快
  • ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令import时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值
  • import命令具有提升效果,因为是编译时加载,所以会比其他代码都先执行

    推荐阅读