node.js 的模块化

模块的概念

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块加载系统。

在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块),换言之,一个 Node.js 文件就是一个模块

模块是Node.js 应用程序的基本组成部分,每个模块都有自己的作用域

 

 

 

在 Node中,模块分为两类

一类是 Node 提供的模块,称为核心模块;另一类是用户编写的模块,称为文件模块。 

核心模块部分在 Node 源代码的编译过程中,编译进了二进制执行文件。在 Node 进 程启动时,部分核心模块就被直接加载进内存中,所以这部分核心模块引入时,文件定位和 编译执行这两个步骤可以省略掉,并且在路径分析中优先判断,所以它的加载速度是最快的。 如:HTTP 模块 、URL 模块、Fs模块都是 nodejs 内置的核心模块,可以直接引入使用。

文件模块则是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、 速度相比核心模块稍微慢一些,但是用的非常多。这些模块需要我们自己定义。接下来我 们看一下 nodejs 中的自定义模块

 

 

当前模块下的内置属性__filename

在node中,这个属性不属于全局的,是数据当前模块的,每个模块都有这样的一个属性返回当前执行的文件的文件路径该路径是经过解析后的绝对路径,在模块中,该路径是模块文件的路径

node.js 的模块化

 

 

require(模块)加载示例

创建一个模块,在另外一个模块中加载上面那个模块,运行测试

node.js 的模块化

node.js 的模块化

node.js 的模块化

 

 

模块加载机制

模块路径可以是一个以 / 开头,表示一个绝对路径 模块路径以 ./ 开头,表示当前目录下的一个相对路径

模块路径如果没有以 / 或者 ./开头,那么这个模块要么是 核心模块(node自带的系统模块) 要么是 node_modules文件夹下的 所以,需要注意的是 ./ 和 没有 ./或/ 开头的路径是和我们常理上的使用结果是不一样的

模块加载中使用绝对路径:模块路径可以是一个以 /  开头,表示一个绝对路径

node.js 的模块化

模块加载中使用相对路径: 在node中相对路径一定要./开头,表示当前路径下,因为不加./的话,node会认为你加载的是原生模块或者是项目下面的node_modules文件夹下面的模块

node.js 的模块化

模块加载机制中文件查找规则:如果按照文件名没有找到,那么node 自动会在文件名后面添加.js继续查找加载,如果还没有找到则会添加.json,如果还没有,则添加.node,还没有,则报错

顺序依次是 文件名 -> 文件名.js -> 文件名.json -> 文件名.node -> 错误

 

 

模块之间数据的使用

模块之间数据的使用中的作用域

在 node 中,每一个模块都有自己的作用域,在模块中使用var申明的变量的作用域范围是在该模块内,而不是node全局的 一个模块中直接去访问另外一个模块中使用var声明的变量是不允许的,会报错

node.js 的模块化

node.js 的模块化

node.js 的模块化

模块之间数据访问的方式一:把变量作为global对象的一个属性,但是这种方式是不推荐的

node.js 的模块化

node.js 的模块化

node.js 的模块化

模块下的module对象

使用module对象,在 node 中,每一个模块都有自己的作用域,同时还有一个 module 的变量,他代表了对当前模块的引用,但是并不是全局对象,并且每个模块都有自己的独立的 module 对象

module对象 : 保存提供和当前模块有关的一些信息

node.js 的模块化

node.js 的模块化

模块之间数据访问的方式二与exports对象
在这个module对象,有一个子对象:exports 对象,我们可以通过这个对象把一个模块中的局部变量对象进行提供访问

node.js 的模块化

node.js 的模块化

module、module.exports、exports三者之间的关系

我们可以通过module.exports 或者 exports 对外提供模块内部变量的访问 外部模块通过require(模块)方法加载模块,该函数返回的就是被加载模块的 module.exports 对象

在模块作用域,还有一个内置的模块对象,exports,他其实就是module.exports

node.js 的模块化

node.js 的模块化

因为module.expotrs===exports所以可以写成下面的这种方式

node.js 的模块化

node.js 的模块化

使用exports需要注意的地方

注意的是最好不要直接覆盖exports或者module.exports,比如 exports=1,module.exports=1,这样做会破坏exports 和 module.exports 的引用关系

node.js 的模块化

node.js 的模块化

 

 

module其他对象

module.loaded:模块是否已经加载完成,或正在加载中。

module.parent:最先引用该模块的模块。

module.paths:模块的搜索路径

module.id:模块的标识符。 通常是完全解析后的文件名。

 

 

node.js中的模块的调用示例

首先创建一个User.js模块,并且将其导出

class User{
    constructor(id,name,age){
        this.id = id;
        this.name = name;
        this.age = age;
    }
    enter(){
        console.log(this.name +"进入图书馆");
    }
}

module.exports = User;

再创建一个Teacher.js模块,模块中引入User.js模块,并且再模块中定义一个Teacher类继承User类

var User = require('./User');

class Teacher extends User{
    constructor(id,name,age,color){
        super(id,name,age);
        this.color = color
    }

    teach(res){
        res.write(this.name+"穿着"+this.color+"的衣服进入图书馆");
    }
}

module.exports = Teacher;

最后再app.js中引入Teacher.js模块,并且创建Teacher对象调用Teacher中的方法

var http = require('http');
var Teacher = require('./Teacher')

http.createServer(function (request,response) {
    response.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
    if(request.url !== "/favicon.ico"){
        teacher = new Teacher(1,"胡椒粉",19,"red");
        teacher.enter();
        teacher.teach(response);

        response.end();
    }
}).listen(9000)

启动服务,浏览器访问

node.js 的模块化

node.js 的模块化