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('爱'));
复制代码

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

带你一起撸一遍 nodejs 常用核心模块(一)相关推荐

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

    前沿:核心模块二主要是和流相关的部分,当然要想给这一块有清楚的了解,你需要对核心模块(一)中的内容有一些了解. fs模块 fs模块的常见方法(所有的读方法,文件必须存在,不存在就会报错,所有的写方法, ...

  2. nodejs常用核心模块介绍

    Node核心模块之HTTP模块 作用:处理客户端的网络请求代码步骤:1.导入 HTTP 核心模块2.监听客户端的请求3.处理客户端的请求4.开启服务器 Node核心模块之URL模块 作用:处理客户端请 ...

  3. 炒鸡简单,带你快速撸一遍Numpy代码!

    作者:贾胜杰,硕士,退役军人,电气工程专业,现成功转行K12领域数据挖掘工程师,不仅在数据清理.分析和预测方向,而且在自制力和高效学习方面都有丰富经验. 编辑:王老湿 我们一起来学习Python数据分 ...

  4. python处理数据0和负数跳过_Python第十一章-常用的核心模块03-json模块

    python 自称 "Batteries included"(自带电池, 自备干粮?), 就是因为他提供了很多内置的模块, 使用这些模块无需安装和配置即可使用. 本章主要介绍 py ...

  5. nodejs没有net模块_Node.js实战16:用http模块创建web服务器

    Nodejs的http模块,是基于net.server,经过c++二次封装,也是nodejs的核心模块. 功能比net.server更强,可解析和操作更多细节内容,如值.content-length. ...

  6. nodejs基础 ps模块常用API用法

    nodejs的fs模块就是针对文件和文件夹进行一系列的操作 常用的fs模块API(感兴趣的可以去node官网看更多的) fs.readFile():用来读取文件内容的函数 fs.readdir():读 ...

  7. 带着问题撸源码系列-zookeeper-临时节点[ephemeral]是怎么弄的?我写了一堆临时节点为啥我一掉线就全没了?

    问题 带着问题撸源码系列-zookeeper-临时节点[ephemeral]是怎么弄的?我写了一堆临时节点为啥我一掉线就全没了? 猜测 可能是有线程维护着,每个session有一个临时节点列表,一旦客 ...

  8. 百度工程师带你体验引擎中的nodejs

    作者 | 糖果candy 导读 如果你是一个前端程序员,你不懂得像PHP.Python或Ruby等动态编程语言,然后你想创建自己的服务,那么Node.js是一个非常好的选择. Node.js 是运行在 ...

  9. NodeJS 常用模块推荐

    cluster&forever cluster & forever 虽然 nodejs 原生已经提供了 cluster 模块,大部分情况下可以满足我们的基本需求,但这两个模块 clus ...

  10. NodeJS 加密 —— crypto 模块

    原文出自:https://www.pandashen.com 加密简介 加密是以某种算法改变原有的信息数据,使得未授权用户即使获得了已加密信息,因不知解密的方法,无法得知信息真正的含义,通过这种方式提 ...

最新文章

  1. 国家公布人工智能四大平台 AI的春天到了?
  2. java restful netty_Java RESTful 框架的性能比较
  3. HDU - 3613 Best Reward(字符串哈希)
  4. GitHub标星6000+!Python带你实践机器学习圣经PRML
  5. 华为Mate40系列安兔兔跑分曝光:麒麟9000性能超骁龙865
  6. Grafana展示DNS解析延时
  7. 瑞士加密银行SEBA将发行B轮融资股票作为证券代币
  8. 2.郝斌C语言笔记——优缺点
  9. 开发技巧 | Python极简实现滑动平均滤波(基于Numpy.convolve)
  10. UVA1386 Cellular Automaton
  11. veu3路由的安装和使用
  12. matlab从无到有系列(二):矩阵运算基础
  13. RPC框架的使用场景
  14. oracle to_char 进制转换_ORACLE函数TO_CHAR以及数字转换格式
  15. 又一个吊打百度网盘的开源神器,还是99年妹子开发的
  16. proximal Algorithm
  17. 什么是P=NP问题?
  18. ubuntu18.04 安装Pangolin
  19. Buffon投针实验 · 数学的直观理解 · 基础知识很重要
  20. [当人工智能遇上安全] 5.基于机器学习算法的主机恶意代码识别研究

热门文章

  1. 微信人工客服终于来了,但是「此」微信客服非「彼」微信客服
  2. ShareKitnbsp;中SHK.m中的编译错…
  3. Rabbit基础概念
  4. 网络协议之Netflow与sFlow协议
  5. 关于SAP的用户出口
  6. 利用一种新的灵活记分卡方法改进肽抗癌活性的预测和表征
  7. 中考考试的指令广播_中考考试指令系统使用的说明.doc
  8. SSM整合(Spring+SpringMVC+MyBatis)
  9. 多模块项目提示“Module ** must not contain source root **. The root already belongs to module **”的解决办法
  10. 7-3 求分数序列前N项和 (15分)