Node之Buffer详解
// const buffer = new Buffer(10); // console.log('buffer', buffer.length);
//下面这些是在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)) { //这里就是我们前面第一种实例化的源代码逻辑部分。
} 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
最后更新于
这有帮助吗?