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

说说CommonJS和ES6Module的使用和区别

时间:2023-04-03 11:58:38 Node.js

学习了JS和使用过Node.js后,你应该对模块化有一定的了解和使用,那么下面两种导入导出模块的方式你一定见过。第一种类型:ES6Module//B.jsfunctionshow(){console.log('show方法被执行')}exportdefaultshow//A.jsimportshowfrom'./B.js'show()//show方法被执行执行第二种:CommonJS//B.jsfunctionshow(){console.log('show方法被执行')}module.exports={show}//A.jsconstbModule=require('./B.js')bModule.show()//执行了show方法以上两种导入导出方法涉及到两个模块规范,分别是ES6Module和CommonJS。本文将谈谈两者的具体使用和区别。1.CommonJSCommonJS2009年,JavaScript社区提出了一个包含模块化的标准,后来被Node.js采纳并实现。也就是说我们在Node.js中使用的模块的导入导出都是按照CommonJS标准实现的。1.1导出我们可以把一个文件看成一个模块,每个模块都是相互独立的,即不会相互影响。当需要使用某个模块时,只需要在文件中导入目标模块即可。如果要被其他模块导入,首先需要导出需要暴露的变量或方法。CommonJS中有两种导出语法的方式//B.js//定义函数showfunctionshow(){console.log('showmethodiscalled')}//定义变量countletcount=3/*-------------exportmethod--------------*///第一种module.exports={show,count}//第二种exports.show=showexports.count=count上面代码中,两种导出方式是等价的。第一种导出方法是将要导出的函数或变量存放在module.exports中,其中module.exports本来就是一个空对象。在第二种export方式中,exports内部其实是指向module.exports的,所以当我们执行exports.variable或者exports.function的时候,其实相当于把变量或者函数存入了module.exports中注意:这里需要强调一下那就是在使用第二种export方式的时候,exports是不能重新赋值的,否则直接在1.2Import中覆盖所有module.exports再看CommonJS的import语法//A.jsconstbModule=require('./B.js')console.log(bModule.count)//3bModule.show()//调用了show方法从上面的代码可以看出,CommonJS通过require方法导入模块,其参数为模块文件的路径.需要注意的是,我们导入模块后接收到的其实是一个对象,也就是module.exports的值,我们可以从这个对象中获取需要的变量或者函数另外,require方法还可以接收一个表达式作为参数,代码如下letfileName='B.js'constbModule=require('./'+fileName)因此,我们可以动态改变和确定模块的加载导入路径2.ES6Module正如标题所说,这个模块标准是在ES6中才提出来的,从此JS有了模块化的特性2.1Export在ES6Module中,使用关键字export进行导出,导出方式大致分为两种,命名为export和默认导出。第一种:namedexport//B.js/*--------单变量或函数export----------*/exportfunctionshow(){console.log('显示方法被调用')}exportletcount=3/*--------批量导出----------*/functionshow(){console.log('显示方法被调用')}letcount=3export{显示,计数}上面的代码分为两种情况,两种写法是等价的。第一种是导出单个变量或函数,一开始直接使用export关键字即可;第二种情况是批量导出多个变量或函数,只需要将它们存储在一个对象中即可。第二种:defaultexport//B.jsfunctionshow(){console.log('调用了show方法')}//命名导出变量countexportletcount=3//默认导出函数showexportdefaultshow的默认导出就是在export关键字后面跟一个default,表示导出的变量或函数是匿名的注意:一个模块默认只能导出一次,否则会报错,具体原因在后面2.2导入ES6中说明Moduleimport使用的关键字是import,具体代码如下3ES6Module的导入需要一对{}花括号来接收我们需要导入的方法或函数注意:花括号中的变量或函数名称必须与导出时的名称完全一致,所以如果我们要修改导入的变量或函数的名称,可以通过as关键字命名,代码如下//A.jsimport{showasprint,countasnumber}from'./B.js'print()//Theshow方法调用console.log(number)//3如果我们要导入所有的变量或者函数,可以通过*整体导入,代码如下import*asbModulefrom'./B.js'bModule.show()//show方法调用了console.log(bModule.count)//3*表示全部,我们全部导入并赋值给bModule,这样我们就可以通过bModule得到想要的变量或者对象它是针对命名的导出变量或函数,那么如何导入一个默认的导出变量或函数呢?//导入exportdefault导出的变量importprintfrom'./B.js'print()//调用show方法命名导出的变量都是通过{}接收的,然后去掉{},接收的变量就是默认导出的变量,因为导出的变量是匿名的,所以我们可以选择一个变量名接收补充:这里特别提一下,不像CommonJS,ES6Module的导入文件路径不支持表达式3、CommonJS和ES6Module的区别两者的主要区别如下:对于模块依赖,CommonJS是动态的,而ES6Module是静态的CommonJS导入的是一个副本值,而ES6模块导入的是对该值的引用。3.1区别1.依赖模块,什么是动态的?什么是静电?动态是指在代码执行阶段就建立了对模块的依赖;static表示在代码编译阶段就建立了对模块的依赖;上面说了CommonJS导入的时候,require的path参数是支持表达式的,比如//A.jsletfileName='example.js'constbModule=require('./'+fileName)因为路径是可以动态改变的代码执行时,如果在代码编译阶段就建立了各个模块的依赖关系,那么肯定是不准确的。只有代码运行后才能真正确定模块的依赖关系,所以CommonJS是动态的那么现在你应该也知道为什么ES6Module是静态的了吧?3.2区别2为了验证这一点,我将用一个例子来演示。首先验证CommonJS,代码如下//B.jsletcount=3functionchange(){count++//变量count+1console.log('原count值为:',count);//打印B.js模块中count的值}module.exports={count,change}//A.jsletcount=require('./B.js').countletchange=require('./B.js').changeconsole.log('变更前:',count);change()//调用模块B.js中的change方法,原来的count+1console.log('Afterchange:',count);//运行A.js文件变化前的结果:3原来的计数值:4变化后:3在上面的代码中我们可以看到B.js文件中的变量count和函数变化是在A.js文件,因为导入的count只是原值的一个副本,所以虽然我们调用函数change改变了B.js文件中变量count的值,但不会影响到A中的变量count。.js文件。根据这个结果,可以断定CommonJS导入的变量是原始值的副本。接下来我们来验证ES6Module。代码如下//B.jsletcount=3functionchange(){count++//variablecount+1console.log(count);//打印模块B.js中count的值}export{count,change}//A.jsimport{count,change}from'./B.js';console.log('beforechange:',count);change()//调用模块B.js中的change方法,改变原来的count+1console.log('Afterchange:',count);//运行A.js文件修改前的结果:3原count值:4修改后:4与CommonJS的结果相比,ES6Module导入的变量count随着原值的变化发生了变化。根据这个结果,得出一个结论:ES6Module导入的变量是对原值的引用4.结束本文到此结束,关于CommonJS和ES6Module,还有一些本文没有提到的知识,希望了解更多可以关注公众号:前端印象,每天分享一篇优质的前端技术文章,还能接收丰富的前端资讯