带你一起撸一遍 nodejs 常用核心模块(一)

本文深入探讨了Node.js中的核心概念module.exports、exports和require的工作原理,并提供了详细的代码示例。此外,还介绍了宏任务与微任务的概念、不同进制之间的转换方法、util模块的常用功能、发布订阅模式的应用、Buffer的声明方式及其常用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

module.exports,exports,require

为什么给这两个单独拿出来放前面说,因为太重要了! 先用人话解释一下:module就是require的时候创建的一个对象,并且返回了 module.exports,exports = module.exports;(牢牢记住) 我们来看自己实现一个:

let path = require('path');
let fs = require('fs');
let vm = require('vm');
function Module(filename) {  //构造函数
    this.loaded = false;
    this.filename = filename;
    this.exports = {}          //模块对应的导出结果
}
Module._extensions = ['.js', '.json']  //静态属性

Module._resolveFilename = function(p) {  //静态方法
    p = path.join(__dirname, p);
    if (!/\.\w+$/.test(p)) {
        for (let i = 0; i<Module._extensions.length; i++) {
            let filepath = p + Module._extensions[i];

            try{
                fs.accessSync(filepath);
                return filepath;
            } catch(e) {
                if(i >= Module._extensions.length) {
                    throw new Error('module not Found')
                }
            }

        }
    } else {
        return p
    }
}
Module._cache = {};    //静态属性 外部无法更改 无法调用

Module._extensions['.json'] = function (module) {
    let content = fs.readFileSync(module.filename,'utf8');
    module.exports = JSON.parse(content)
}
Module.wrapper = ['(function (exports,require,module){','\r\n})'];  
//通过这个包裹 使得exports = module.exports;
Module.wrap = function (content) {
  return Module.wrapper[0] + content + Module.wrapper[1];
}
Module._extensions['.js'] = function (module) {
  let content = fs.readFileSync(module.filename, 'utf8');
  let script = Module.wrap(content);
  let fn = vm.runInThisContext(script);
//   module.exports = exports = {}
  // exports.a = 'hello world'
  fn.call(module.exports, module.exports, req, module);
}
Module.prototype.load = function () {
  // 加载模块本身 js按照js加载 json按照json加载
  let extname = path.extname(this.filename);
  Module._extensions[extname](this);
}



Module.prototype.load = function () {
    let extname = path.extname(this.filename);
    Module._extensions[extname](this)       //模块的执行
}

//重点require就是给module.exports导出的代码包了一层,然后module.load()执行并取得返回值
function req(path) {                    
    let filename = Module._resolveFilename(path);
    if (Module._cache[filename]) {
        return Module._cache[filename].exports;
    }
    let module = new Module(filename)
    module.load();  //让这个模块进行加载 根据不同的后缀加载不同的内容
    Module._cache[fileName] = module;
    return module.exports;
}

复制代码

宏任务&微任务

进制

数字按照进制可分为二进制,八进制,十进制和十六进制,在计算机内部呢都是使用的二进制,node中各种进制的表示:

  • ob表示二进制 ,
  • 0o或者0表示八进制,
  • 0x表示16进制(buffer都是用16进制表示,buffer是啥?后面会说道到)

这些进制之间怎么转换呢? 各种进制转化为十进制用Math.parseInt();十进制转为其他进制可以利用toString()方法。

util模块

  1. util.promisify(fn); //十分常用
  2. util.inherits(Child, Parent);
  3. util.isArray([]) util.isString();

发布订阅

let EventEmitter = require('./events');
let util = require('util');
function My() {}
util.inherits(My,EventEmitter);
let e = new My();
// 订阅
e.on('水开了',function (who) { // {水开了:[fn,fn]}
  console.log('吃泡面' + who)
});
e.on('水开了',function (who) {
  console.log('洗脸' + who);
});
// 发布
e.emit('水开了','我') 
复制代码

这个地方有一个主意的地方就是 e.on('newListener', cb) 2.

let EventEmitter = require('events');
let util = require('util');
function My() {}
util.inherits(My,EventEmitter);
let e = new My();
e.on('newListener',function (type) {
  if(type === 'ok'){
    process.nextTick(()=>{    //这个要注意 必须事件已经被添加进去后才可以触发
      e.emit('ok');
    });
  }
})
e.on('水开了',function (who) {
  console.log('吃泡面' + who)
});
e.on('水开了',function (who) {
  console.log('洗脸' + who);
});
e.on('ok',function () {
  console.log('ok')
})
复制代码
  1. e.once(event, cb)
  2. e.removeListener(event, cb)

Buffer

怎么声明buffer

  1. 通过长度 let buffer = Buffer.alloc(length);
  2. 通过字符串声明 let buffer = Buffer.from('字符串');
  3. 通过数组声明 let buffer = Buffer.from([0xe7, 0x8f,0xa0])

另外说明一点的是:buffer是内存地址的引用,可以修改的


buffer的几个常见方法:

  • buffer.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
  • Buffer.concat(list[, totalLength]) //和数组类似
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;

// 输出: 42
console.log(totalLength);

const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);

// 输出: <Buffer 00 00 00 00 ...>
console.log(bufA);

// 输出: 42
console.log(bufA.length);
复制代码

有时我们需要给一段字符串进行切割,就像字符串的split方法一样,但是buffer并没有提供一个这样的方法,我们自己实现一个吧,代码如下:

// indexOf 取索引
let buffer = Buffer.from('xlei爱折腾爱js');
// console.log(buffer.indexOf('*',7));
Buffer.prototype.split = function (sep) {
  let offset = 0;
  let len = Buffer.from(sep).length;
  let arr = [];
  let start = 0;
  while (-1 != (offset = (this.indexOf(sep, start)))) {
    arr.push(this.slice(start, offset));
    start = offset + len;
  };
  arr.push(this.slice(start));
  return arr;
}
// spilt()方法 分割buffer
// [buffer1,buffer2,buffer3]
console.log(buffer.split('爱'));
复制代码

以上是一部分的核心模块常见用法以及部分深刻解析,不足之处欢迎各位提出宝贵的意见或建议,也希望能帮助到你从中获得一些知识!这是一个系列的文章 还有核心模块(二)核心模块(三)等等部分,谢谢大家的关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值