首页 > 网站 > WEB开发 > 正文

NodeJS的模块机制

2024-04-27 15:09:07
字体:
来源:转载
供稿:网友

一、前言

Node应用是由模块组成的,Node遵循了CommonJS的模块规范,来隔离每个模块的作用域,使每个模块在它自身的命名空间中执行。

CommonJS规范的主要内容:

模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。

CommonJS模块的特点:

(1)所有代码运行在当前模块作用域中,不会污染全局作用域 (2)模块同步加载,根据代码中出现的顺序依次加载 (3)模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。

一个简单的例子:

//demo.jsmodule.exports.name = 'Aphasia';module.exports.getAge = function(age){ console.log(age)};//需要引入demo.js的其他文件var person = require('./demo.js')

二、module对象

根据CommonJS规范,每一个文件就是一个模块,在每个模块中,都会有一个module对象,这个对象就指向当前的模块。module对象具有以下属性:

(1)id:当前模块的bi (2)exports:表示当前模块暴露给外部的值 (3)parent: 是一个对象,表示调用当前模块的模块 (4)children:是一个对象,表示当前模块调用的模块 (5)filename:模块的绝对路径 (6)paths:从当前文件目录开始查找node_modules目录;然后依次进入父目录,查找父目录下的node_modules目录;依次迭代,直到根目录下的node_modules目录 (7)loaded:一个布尔值,表示当前模块是否已经被完全加载

示例:

module.js文件 这里写图片描述

执行node module.js文件 这里写图片描述

(一)exports属性

从上面的例子我们也能看到,module对象具有一个exports属性,该属性就是用来对外暴露变量、方法或整个模块的。当其他的文件require进来该模块的时候,实际上就是读取了该模块module对象的exports属性。

简单的使用示例

module.exports = 'Aphasia';module.exports.name = 'Aphasia';module.exports = function(){ //dosomething}module.exports = { name: 'Aphasia', getAge: function(){ //dosomething }}
(二)exports变量

为什么还有个exports变量呢?一开始我也很郁闷,既然module.exports就能满足所有的需求,干嘛还要个exports呢。其实,原因很简单–就是为了简单。当然,二者之间还存在一些差异,听我慢慢道来。

(1)exports其实是指向module.exports,也就是相当于

exports = module.exports;

(2)我们可以将二者的关系可以理解成这是一种引用关系。由于这样的引用关系可知,既然exports始终指向的是module.exports,那我们就不能给exports直接进行赋值操作(不能乱指),因为这样的操作会导致exports不再指向module.exports。

//以下操作都是不允许的exports = 'Aphasia';exports = function(){ console.log('Aphasia')}//这些操作都是合法的exports.name = 'Aphasia';exports.getName = function(){ console.log('Aphasia')}

三、require命令

(1)exports用来抛出一个接口,require就是用来引入这个模块抛出的接口,返回引入模块的exports对象,如果没有找到该模块,就会报错。 (2)使用require引入的文件,文件名后缀默认为.js

引入规则

既然是用来引入一个模块,就需要有一定的查找规则以确定需要引入的模块究竟存在哪里。

enter image description here

根据上面的流程图,其实可以看出以下几点: (1)被引入的模块优先从缓存中加载,命中缓存直接加载;未命中,之后会被加入缓存。 (2)如果不是node的原生模块,则根据传入到require中的参数引入模块。这一过程的查找规则如下:

如果路径是以/开始的绝对路径,就从该项目的绝对路径中去加载该模块。比如:require(“/demo/lib/api.js”),就会从/demo/lib/api.js中去加载该模块 如果路径是以./开始的相对路径,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如,require(‘./circle’)将加载当前脚本同一目录的circle.js
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表