当前位置: 首页 > 后端技术 > Node.js

前端常用的4种模块化方案总结,md

时间:2023-04-03 23:22:32 Node.js

JS为简单的页面开发而生,没有模块的概念。后来页面越来越复杂,人类构造了IIFE来立即执行函数来模拟模块;Yahoo之前也使用名称空间作为模块名称。最后衍生出各种使用场景的JS模块标准。比如:浏览器的AMD,Nodejs的CommonJS,ES标准也在想尽办法弥合这种分裂状态。但是目前流行的做法是UMD模式。1AMDAMD是requirejs推动的规范,主要用于浏览器环境。它通过define和require来定义和调用模块。定义模块define("alpha",["require","exports","beta"],function(require,exports,beta){exports.verb=function(){returnbeta.verb();//或者:returnrequire("beta").verb();}});//返回对象的匿名模块define(["alpha"],function(alpha){return{verb:function(){returnalpha.verb()+2;}};});调用模块require(['foo','bar'],function(foo,bar){foo.doSomething();});define(function(require){require(['a','b'],function(a,b){//模块a和b现在可以使用了。});});2commonJSNode应用由模块组成,采用CommonJS模块规范。每个文件都是一个模块,有自己的作用域。文件中定义的变量、函数和类都是私有的,对其他文件不可见。CommonJS加载模块是同步的,所以后续操作只能在加载完成后进行。例如,Node.js主要用于服务器编程。加载的模块文件一般已经存在于本地硬盘,所以加载比较快,不需要考虑异步加载的方式,所以CommonJS规范更适用。但是如果是浏览器环境,要从服务端加载模块,就必须使用异步方式。于是就有了AMDCMD的解决方案。//a.js//相当于这里的另一行:varexports=module.exports;代码exports.a='Helloworld';//相当于:module.exports.a='Helloworld';//b.jsvarmoduleA=require('./a.js');console.log(moduleA.a);//打印出helloworld3UMD兼容AMD和commonjs,也兼容全局变量定义的通用模块化规范(function(root,factory)){if(typeofdefine==='function'&&define.amd){//AMDdefine(['jquery'],factory);}elseif(typeofexports==='object'){//Node,CommonJS-likemodule.exports=factory(require('jquery'));}else{//浏览器全局变量(根是窗口)root.returnExports=factory(root.jQuery);}}(this,function($){functiona(){};//私有方法,因为它没有被返回(见below)functionb(){};//公共方法,因为它被返回functionc(){};//公共方法,因为它被返回//暴露公共方法return{b:b,c:c}}));4ES6ModuleES6在语言标准层面实现了模块功能,实现起来相当简单,旨在成为浏览器和服务器通用的模块化解决方案。它的模块功能主要由两个命令组成:export和import。export命令用于指定模块的对外接口,导出模块暴露的API;import命令用于导入其他模块提供的功能,导入其他模块。/**定义模块math.js**/varbasicNum=0;varadd=function(a,b){returna+b;};export{basicNum,add};/**引用模块**/import{basicNum,add}from'./math';functiontest(ele){ele.textContent=add(99+basicNum);}5ES6模块和CommonJS模块的区别CommonJS模块输出一个值的副本,而ES6模块输出是对值的引用。CommonJS模块输出值的副本,即一旦输出值,模块内部的更改不会影响该值。ES6模块的工作方式与CommonJS不同。JS引擎静态分析脚本时,遇到模块加载命令import时会生成一个只读引用。当脚本真正执行时,根据只读引用去加载模块获取值。也就是说,ES6的导入有点像Unix系统的“符号链接”。当原值改变时,import加载的值也会改变。因此,ES6模块是动态引用,不缓存值。模块中的变量绑定到它们所在的模块。CommonJS模块在运行时加载,而ES6模块是编译时输出接口。运行时加载:CommonJS模块是对象;即在输入的时候,先加载整个模块,生成一个对象,然后从对象中读取方法。这种加载称为“运行时加载”。编译时加载:ES6模块不是对象,而是通过export命令明确指定输出代码,导入时使用static命令。即在导入时,可以指定加载某个输出值,而不是加载整个模块。这种加载称为“编译时加载”。CommonJS加载的是一个对象(即module.exports属性),只有在脚本运行完毕后才会生成。ES6模块不是对象,它的对外接口只是一个静态定义,会在代码的静态分析阶段生成。