Node之Buffer详解

// const buffer = new Buffer(10); // console.log('buffer', buffer.length);

const buf = new Buffer([1,2,3])
console.log('buf', buf)

//下面这些是在Buffer构造函数中使用到的一些基本的方法:

//smalloc为内存操作的对象 var smalloc = process.binding('smalloc');

//util为工具函数,包含一些基本的操作方法 var util = require('util');

//alloc对象用于生成一段内存的方法 var alloc = smalloc.alloc;

//truncate类似于一个查找方法,比如在数据库中根据一定的条件查表。 var truncate = smalloc.truncate;

//我的理解,这个sliceOnto是属于合并拼接内存区间所用 var sliceOnto = smalloc.sliceOnto;

//kMaxLength为生成内存区间的最大容量 var kMaxLength = smalloc.kMaxLength;

//pollSize表示自定义的一个值 Buffer.poolSize = 8 * 1024;

var poolSize, poolOffset, allocPool; //定义的三个全局变量,也算是闭包内的私有变量

//上述的含义,是我再读源码时,按照当时的逻辑理解的意思,还没有去看相关部分的源码,所以,如果有任何疑问,请指教。

//createPool用于生成一个内存区间的,并把生成的内存区间存入allocPool function createPool() { poolSize = Buffer.poolSize; allocPool = alloc({}, poolSize); //allocPool保存生成的一段大小为poolSize的内存区间 poolOffset = 0; //在生成的内存中使用位置的偏移量,用于保存当前内存区间的使用量, //防止被后面的数据覆盖掉。 } createPool(); //先生成一段供使用

//下述构造函数中,英文注释是源码中的注释,中文是我的理解注释。 function Buffer(subject, encoding) { if (!util.isBuffer(this)){ //如果忘记使用new ,则重定义 return new Buffer(subject, encoding); }

if (util.isNumber(subject)) { //这里就是我们前面第一种实例化的源代码逻辑部分。

//如果第一个参数是一个数字,那么把该数字,定义为数组的长度
this.length = +subject;

} else if (util.isString(subject)) { //实例化时,第三种实例化源码逻辑处理

// Handle Arrays, Buffers, Uint8Arrays or JSON. } else if (util.isObject(subject)) { //构造函数第二种实例化处理逻辑

} else { //否则,抛出一个错误,第一个参数的类型, //必须是固定的四种类型,其他类型是不被支持的。 throw new TypeError('must start with number, buffer, array or string'); }

//判断数组长度,是否超出最大长度,也就是数组时否溢出。 if (this.length > kMaxLength) { //如果当前的buffer数组,过长,则抛出一个“范围异常” throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength.toString(16) + ' bytes'); }

//判断当前数组的长度是否小于0,如果是,则置为0 if (this.length < 0) this.length = 0; else this.length >>>= 0; // Coerce to uint32. //无符号右移,变化为数字的方法

this.parent = undefined; if (this.length <= (Buffer.poolSize >>> 1) && this.length > 0) { //在判断是否需要重新分配内存空间,不需要生成的话,则执行该部分逻辑 //如果需要生成的内存buffer的大小,占生成内存区间大小的一半之上的话 //则重新分配一整段的内存区间,存放该数据 if (this.length > poolSize - poolOffset){ //需要重新分配内存区间 createPool(); }

} else { //给该数据,生成一个单独的静态内存区间,保存数据 alloc(this, this.length); }

if (util.isNumber(subject)) { //如果第一个参数是数字,那么这里就可以结束了。 return; }

if (util.isString(subject)) { // In the case of base64 it's possible that the size of the buffer // allocated was slightly too large. In this case we need to rewrite // the length to the actual length written. var len = this.write(subject, encoding); //调用buffer对象的write方法,write方法,后面再看~ // Buffer was truncated after decode, realloc internal ExternalArray //如果当前的第一个参数是字符串,那么就把该字符串根据encoding的类型,写入到this的buffer对象上去

} else if (util.isBuffer(subject)) { //第二种和第三种构造函数使用时,初始化数据到buffer对象中去。 //如果当前对象为Buffer对象, //则把subject对象上的数据,保存到this对象上 subject.copy(this, 0, 0, this.length);

} else if (util.isNumber(subject.length) || util.isArray(subject)) { // Really crappy way to handle Uint8Arrays, but V8 doesn't give a simple // way to access the data from the C++ API. //如果subject是数组的话,则~~使用数组赋值 for (var i = 0; i< this.length; i++) this[i] = subject[i]; }

//构造函数,返回this对象,即一个新的buffer对象 }

浏览器端

var buf = new ArrayBuffer(32); buf.length //32

var arr = new Unit16Array(buf); arr.length //16

最后更新于

这有帮助吗?