Nodejs的模块化概述
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.COMMON JS规范
1>.ECMA Script 5标准的缺陷
早期ECMA Script 5标准的缺陷概述: (1)在ECMA Script 5中是没有模块系统,但是有模块化的组件,比如Jquery,但并非模块化系统,在ECMA Script 6是有较为完整的模块化系统了; (2)标准库较少; (3)没有标准接口; (4)缺乏管理系统,比如咱们想要安装Jquery,Vue,React等开源组件需要程序员自行去相应的官网下载安装,因此在早期的ECMA Script 5中,缺少类似python的pip包管理工具。 综上所述,我们需要模块话技术: (1)如果程序的规模达到了一定的程度,则必须对其进行模块化; (2)模块化可以有多种形式,但至少应该提供能够将代码分割为多个源文件的机制; (3)CommonJS的模块功能可以帮我们解决该问题;
2>.Common JS规范
CommonJS规范的提出,主要是为了弥补当前JavaScript没有标准的缺陷。 CommonJS规范为JS指定了一个美好的愿景,希望JS能够在任何地方运行。 CommonJS对模块的定义十分简单,如下所示: (1)模块引用; (2)模块定义; (3)模块标识;
3>.模块的引用
在规范中,定义了require()方法,这个方法接手模块标识,以此将一个模块引入到当前运行环境中。
模块引用的示例代码可参考下面的案例。
4>.模块定义
在运行环境中,提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一的导出的出口。 在模块中还存在一个module对象,它代表模块自身,而exports是module的属性。即"exports=module.exports"。在NodeJS中一个文件就是一个模块。 模块定义的示例代码可参考下面"module.exports和exports的区别"的案例。
5>.模块标识
模块标识其实就是模块的名字,也就是传递给require()方法的参数,它必须是符合驼峰命名法的字符串,或者是以当前目录("."),上级目录("..")开头的相对路径、或者绝对路径。
模块的定义十分简单,接口也十分简洁。每个模块具有独立的空间,它们互不干扰,在引用时也显得干净利落。
模块标识的示例代码可以参考下面的案例。
6>.NodeJS模块的实现
NodeJS中虽然使用的是CommonJS规范,但是其自身也对规范做了一些取舍。
在NodeJS中引入模块,需要经历如下3个步骤: (1)路径分析 (2)文件定位 (3)编译执行
在NodeJS中,模块分为三类:
(1)是底层由C++编写的内建模块;
(2)是Node提供的核心模块(例如"os","sys","fs","path"等模块);
(3)用户编写的模块,称为文件模块。
二.模块化
1>.模块化概述
在开发过程中,我们写程序可以将代码写入到一个文件中,这在你的应用较小时其实并没有什么影响(比如你就想实现一个简单的九九乘法表的功能)。但是如果你的应用程序比较大的话那将整个程序写在同一个文件中是不可取的。
在实际开发中,我们需要将一个程序拆开称为多个模块,将一个大的应用拆开成为多个模块包括但不限于以下几个好处:
(1)可以降低耦合度,如果一个模块对其它的模块依赖度很强,则耦合度也强,我们将耦合度底的模块从主程序中拆解出来,便于以后用于其它的项目,从而降低主程序本身的耦合度;
(2)可以复用现有的代码,比如一个系统包括权限管理,路由分发,视图函数,权限检查等功能,我们可以将其拆开,复用到其它项目中;
(3)从长远的角度看可以降低开发的成本,因为之前开发的项目模块化后,后期的项目可以直接复用之前的模块。
在NodeJS中,任意一个JavaScript文件都是一个独立的模块,各个Javascript模块之间是可以相互引用的。
2>.自定义编写用于被demo.js模块导入的模块
/** * 我们在全局作用域定义的变量并不能跨越模块哟~比如下面我定义了一个list变量,该变量并不能被其它模块导入。 * * 当然,如果您非要将list属性暴露给其它模块,就得将其定义为exports的属性哟~ */ function for66(start=1,stop=6){ for(var i = start; i <= stop; i++){ var list = []; for(var j = 1;j <= i;j++){ result = j + "x" + i + "=" + i * j; list.push(result); } console.log(list); } } /** * 我们可以通过exports来向外部暴露变量和放啊,只需要将需要暴露给外部的变量或方法设置为exports的属性即可。 */ exports.name = "尹正杰"; exports.age = 18; exports.func = for66; /** * 注意哈,我们定义的add函数尽管是全局作用域的变量,但它并不能跨越模块,因此 */ function add(x,y) { return x + y; } console.log(add(10,20))