《深入浅出Node.js》读书笔记+个人思考(一):模块机制

CommonJS对模块的规范

图说 CommonJS

这里写图片描述


1. 模块的引用

  • 使用关键词 require
    var math = require('math');
  • 在文件中不要自己定义 require , 这样会覆盖原有的 require
    //测试文件:require_show.js
    console.log(require);

结果如下:

这里写图片描述


2. 何谓模块

  • 分两大类:

    • 核心模块 (比如: fs, http等node提供的原生模块)
    • 文件模块 (用户自己定义的模块)
  • 分三大类

    • js 类型
    • c/c++ 类型
    • json 类型
  • node 中,一个文件就是一个模块,其中存在一个module对象,代表模块自身

    //测试文件 module_show.js
    console.log(module);

结果如下:

这里写图片描述

其中 path 属性存放的数组代表此模块可能存在的路径,当前文件所在路径为其中 filename 属性所存放的值,也就是数组的第一个,而且这个数组内值的排序就是node寻找指定模块地址的顺序,一层一层目录逐级查找

注意到其中还有一个 exports 属性存放的是一个空对象,这是模块机制的一个重要组成部分,再来一个例子,在之前的文件中的 exports 对象挂载一个方法:

    //测试文件 module_show.js
    module.exports.sayHi = function () {
        console.log('this is module_show.js');
    }
    console.log(module);

结果如下:

这里写图片描述

发现 exports 多了一个方法,那么在另外一个(模块)文件中使用,该文件与之前文件在同一级目录:

    //测试文件 module_use.js
    const obj = require('./module_show.js');
    // 测试 obj 是什么东西
    console.log(obj);
    // 测试是否可以调用sayHi方法
    obj.sayHi();
    //测试文件 module_show.js
    module.exports.sayHi = function () {
        console.log('this is module_show.js');
    }

结果如下:

这里写图片描述

这说明前一个文件的 module.exports 所存放的对象通过 require 赋给了另一个文件中的 obj 变量

另一种情况,如果说 module_show.js 文件如下书写,会如何?

    //测试文件 module_show.js
    // 直接将一个方法赋给 module.exports
    module.exports = function () {
        console.log('this is module_show.js');
    }
    console.log(module);

结果如下

这里写图片描述

module.exports 现在已经不是object对象了,而成为了 Fucntion 类型,所以在另外一个文件中可以直接使用了

    //测试文件 module_use.js
    const obj = require('./module_show.js');
    // 测试 obj 是什么东西
    console.log(obj);
    // 测试是否可以作为方法使用
    obj();
    //测试文件 module_show.js
    module.exports = function () {
        console.log('this is module_show.js');
    }

结果如下:

这里写图片描述

也就是说,require 引入的是那个模块(文件)的 module.exports 的值,原始的 module.exports 为一个对象,可以对其添加属性与方法,也可以将一个全新类型的值赋给它。

说白了,exports 就是一个初始化为 { } 的对象,为module的一个属性,可以被引用到它的别的模块访问,你可以改变其内容,仅此而已

3. 模块标识

  • 定义:传给 require() 方法的参数
  • 内容:
    • 核心模块 : http, fs, path
    • . 或 .. 开始的相对路径文件模块
    • 以 / 开始的绝对路径模块
    • 非路径形式的文件模块

一个模块的真面目

写一个简单的 web 服务器,向页面中写一个 ‘Hello world’

    // module_architect.js
    const http = require('http');

    http.createServer(function (req, res) {
        res.statusCode = 200;
        res.write('Hello world');
        res.end();
    }).listen(4000);

使用 chrome 调试模块

node --inspect module_architect.js

看看在chrome中此文件如何显示的:

这里写图片描述

此模块被封装在一个函数中,而传入函数的参数有 exports ,require, module , __filename, __dirname

好了,出现了新的问题,exportsmodule.export 是什么关系,后面的两个变量又是啥,书写一下模块来看一下

    //测试文件 module_show.js

    //为 module.exports 挂载属性 a 并赋值
    module.exports.a = 1;
    console.log(module.exports);
    console.log(exports);
    console.log('.......');

    //为 exports 挂载属性 b 并赋值,同时改变 a 的值
    exports.a = 2;
    exports.b = 2;
    console.log(module.exports);
    console.log(exports);
    console.log('.......');
    // 查看两个变量的值
    console.log(__filename);
    console.log(__dirname);

结果如下

这里写图片描述

  • 结论一: module.exportsexports 是相同的
  • 结论二:__filename 显示当前文件所在的绝对路径, __dirname 显示当前文件所在文件夹的绝对路径

模块的优势

从上面可以看出,一个模块会被node封装在一个函数中,形成一个闭包,所以可以防止变量污染啦


模块引用的实现

  • 核心模块:路径分析 -> 引入
  • 文件模块:路径分析 -> 文件定位 -> 编译执行
  • 一个 c/c++参与编写的node模块示意图


c/c++编写node模块(此处略去…)

我觉得我的水平还没到这个地步,而且书中篇幅也比较多,所以就跳过了≥.≤


包(package)

包的组织形式

不多说,上图

这里写图片描述

包规范(来自CommonJS)

  • package.json 包描述文件
  • bin 用于存放可执行二进制文件的目录
  • lib 用于存放js代码目录
  • doc 用于存放文档目录
  • test 用于存放单元测试用例的代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值