在node环境中require了一个module1.js做了哪些事
先看一个熟悉的例子1
2
3node-source-code
- index.js
- module1.js
module1.js1
module.exports.content = 'hello hardy'
index.js1
2const module1 = require('./module1')
console.log(module1.content) // hello hardy
why?why console hello hardy
首先要分析一下node代码的执行过程
- 1、默认调用require方法
- 2、模块的原型上有require方法(Module.prototype.require)
- 3、调用模块的加载方法(Module._load), 返回module.exports
- 4、解析文件名(Module._resolveFilename), 找到文件的绝对路径并按顺序尝试添加后缀(.js, .json, .node)
- 5、默认查找是否曾缓存过(Module._cache)
- 6、创建模块(new Module), constructor(id, exports)
- 7、缓存模块
- 8、尝试加载模块
- 9、第三方模块查找路径(module.paths)
- 10、获取模块扩展名,根据扩展名调用对应的方法(Module._extensions, 策略模式)
- 11、fs读取文件内容(utf8)
- 12、编译(module._compile)
- 13、讲用户的内容包裹到一个函数中(function(exports, require, module, filename, dirname) {})
最终返回module.exports, 用户会给module.exports赋值
它在这里: https://github.com/HHardyy/node-source-code
进制转换
常用的进制
- 10进制
- 2进制(0b11)
- 8进制(0o66)
- 16进制(0x16)
进制的互相转化
- 一个字节以8个bit位,编码过程以字节为单位,常见一个字节组成一个字符, 双(三)字节组成一个汉字
- 1、把任意进制转换成10进制,需要用当前位所在的值 * 当前进制^第几位
- | - | - | - | - | - | - | - |
---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
1x2^7 | 1x2^6 | 1x2^5 | 1x2^4 | 1x2^3 | 1x2^2 | 1x2^1 | 1x2^0 |
一个字节代表10进制的话就是255
1 | let sum = 0 |
255再转成16进制
1 | console.log(Math.floor(255 % 16)); // 15 |
所以16进制最大的字节就是0xff
255再转成8进制
1 | console.log(255 % 8); // 7 |
所以10进制转换成任意进制都可以采用取余的方法
1 | // 将任意进制转成10进制 |
在node中需要进行文件读取, node中操作的内容默认会存在内存中,内存中的表现形式肯定是二进制的,二进制转换16进制来展现 11111111 => ff
1 | const fs = require('fs') |
编码的发展
ASCII编码,一些常用的字符和字幕进行了一个排号, 大小(0 - 127), 只会占用一个字节大小, ASCII编码表 https://zh.wikipedia.org/wiki/ASCII
1
console.log(2**7 - 2**0); // 127, 1x2^(6+1) - 1x2^0
gb2312 用两个字节,大小(27000)
- gbk 扩展 40000+
- gb18030 少数民族的汉字
- Unicode
- utf8 (在utf8中一个字符占用一个字节, 一个汉字占用两(三)个字节)
base64
base64没有加密功能(只是编码转化base64), 原理是将3 8 的规则改成了4 6的规则, 什么意思呢, 就是1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 一、字符串转成16进制
let buffer = Buffer.from('圳')
console.log(buffer); // <Buffer e5 9c b3>
// 二、16进制转成2进制
console.log((0xe5).toString(2));
console.log((0x9c).toString(2));
console.log((0xb3).toString(2));
// 3 * 8位规则的二进制
// 11100101 10011100 10110011 => 111001011001110010110011
// 4 * 6位规则的二进制
// 111001011001110010110011 => 111001 011001 110010 110011
// 三、二进制再转成十进制
let arr = ['111001', '011001', '110010', '110011']
arr = arr.map(v => parseInt(v, 2))
console.log(arr);
// [ 57, 25, 50, 51 ]
// 四、再转成base64编码
let str = ''
str += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
str += str.toLowerCase()
str += '0123456789'
str += '+/'
let base64 = ''
arr.forEach((v) => { base64 += str[v] })
console.log(base64); // 5Zyz
再反推回去就可以得到字符串了😅, 但是, 我就不, 但是在這里可以在线解密 base64.us
☂️ 为什么有的图片建议转成base64, 而有些图片不建议转成base64?
- 原因是:举上面的例子,base64转化之前是e5 9c b3三个字符, 但是转换之后(5Zyz)是四个字节, 比原来大了三分之一, 比如原来1M的图片,base64之后比原来更大~, 所以只建议转小图片
☂️ 为什么叫base64, 因为分成每份的值永远不会大于64, 比如将一个二进制全填满1
2// 111001 => 111111 => 00111111
console.log(2 ** 6) // 64
前端的二进制(Blob二进制文件类型)
啥? 前端的文件不是file吗 ?1
2// 答案
<input type="file" /> // 继承于Blob
👉例如在前端我想下载, 和预览1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="file" id="file">
<script>
let str = `<div>hello hardy</div>`
// 1、下载
// 字符串转成二进制类型 => 创建临时下载链接
const blob = new Blob([str], { type: 'text/html' })
const a = document.createElement('a')
a.setAttrbute('download', 'test.html')
a.href = URL.createObjectURL(blob)
a.click()
// 2、预览
file.addEventListener('change', function(e) {
let file = e.target.files[0]
let fileReader = new FileReader()
fileReader.readAsDataURL(file)
fileReader.onload = function () {
console.log(fileReader.result)
}
})
</script>
</body>
</html>
服务端的二进制(Buffer = 二进制数据, 内存)
Buffer可以和字符串相互转化, 不能扩容, 想改动就生成一个新的内存然后拷贝
三种声明方式
通过长度声明(大小)
1
2
3
4
5
6const buffer = Buffer.alloc(5) // 不具备扩展, push, shift等方法
console.log(buffer.slice(0, 1)) // <Buffer 00 00 00 00 00> slice 浅拷贝
let buf = buffer.slice(0, 1)
buf[0] = 100
console.log(buffer); // <Buffer 64 00 00 00 00>根据汉字声明(大小)
1
2const buffer = Buffer.from('小方块')
console.log(buffer.length) // 9 1个汉字3个字符
.。。。待续更新