这篇文章上次修改于 710 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

一个 buffer 缓存就是一个内存空间。JavaScript 开发者相较于 c++/go 等语言的开发者对内存的理解比较少。它表示在 JavaScript V8 engine 之外的分配的一块 fixed-size 固定大小的内存。可以想象 buffer 就是一个 integer 整型数组,每个元素代表一个 byte 的数据。

node.js 中 buffer 通过 Buffer class 实现。

为何需要 buffer

引入 Buffer 是为了帮助开发者处理 binary 二进制数据。传统的 ecosystem 只可以处理 strings 字符串数据。Buffer 和 streams 是紧密关联的,当 stream processor 流处理器接收数据的速度大于其处理速度时,就会先将数据放在 buffer 中。

可以想象下,在我们看在线视频时,在网络较好的情况下进度条中可以看到视频下载的进度是超过当前播放进度的,此时浏览器就会先 buffer 缓存数据后续按时间顺序播放出来。

创建 buffer

可以通过 Buffer.from(), Buffer.alloc()Buffer.allocUnsafe() methods 来创建一个 buffer,下面依次介绍。

使用 Buffer.from() 可以从 array 数组创建 buffer:

const buf1 = Buffer.from('hey!')

使用 Buffer.from(string[, encoding]) 可以设置 string 的编码类型,Default: utf8

const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex')

也可以根据另一个 buffer:

const buf3 = Buffer.from(buf1)

通过 Buffer.alloc()Buffer.allocUnsafe() 来初始化一个指定大小的 buffer,单位为 byte 字节:

const buf4 = Buffer.alloc(1024)
const buf5 = Buffer.allocUnsafe(1024)

以上会创建一个 1kb 大小的 buffer。

通过 alloc 创建的 buffer 会初始化其数据为 0,而 allocUnsafe 创建的 buffer 内的数据会是 uninitiated 未初始化的,这就表示使用 allocUnsafealloc 创建速度更快。但是通过 allocUnsafe 创建的 buffer 内存空间会包含有以前的数据可能引起潜在问题。

使用 buffer

我们可以像访问数组一样访问 buffer 数据:

const buf1 = Buffer.from('hey!')

console.log(buf1[0])
console.log(buf1[1])
console.log(buf1[2])

//output:
//104
//101
//121

这些输出的数字就是代表 buffer 中每个字符的 Unicode Code,h => 104, e => 101, y => 121。

使用 toString() method 可以将 buffer 输出为字符:

console.log(buf1)
console.log(buf1.toString())

//output:
//<Buffer 68 65 79 21>
//hey!

buf1.length 可以读取 buffer 长度:

console.log(buf1.length)

//output:
//4

也可以使用循环 iterate buffer 的数据:

for (const iterator of buf1) {
    console.log(iterator)
}

//output:
104
101
121
33

通过 write() method 可以给 buffer 写入数据:

const buf6 = Buffer.alloc(5)
buf6.write('hello')

也可以像数组一样修改某个元素的数据:

const buf6 = Buffer.alloc(5)
buf6.write('hello')
buf6[0] = 111
console.log(buf6.toString())

//output:
//oello

可以看到需要修改字符对应的 Unicode Code。

使用 copy() method 可以复制 buffer 数据到其他 buffer:

const buf1 = Buffer.from('hey!')
const buf7 = Buffer.alloc(4)
buf1.copy(buf7)
console.log(buf7.toString())

//output:
//hey!

注意是源 buffer 掉用 copy method 来复制数据到目标 buffer。

默认情况下会复制 buffer 的整个数据, copy method 可以设置其他三个参数来自定义目标 buffer 起始接收数据位置,源 buffer 起始复制数据位置,以及复制的新 buffer 的长度:

const buf8 = Buffer.alloc(2)
buf1.copy(buf8, 0, 0, 2)
console.log(buf8.toString())

//output:
//he

可以使用 slice method 来选取 buffer 的一个片段,它和 copy 的不同是 slice 获取的 buffer 片段仍然和源 buffer 相关联,修改源 buffer 会改变片段中的 buffer 数据。

slice 的第一个参数定义起始位置,第二个参数是选项,可以定义终止位置:

const buf1 = Buffer.from('hey!')
const slice = buf1.slice(0, 2)
console.log(slice.toString())
buf1[0] = 111
console.log(slice.toString())

//output:
//he
//oe

以上就是 Buffer 的简单使用方法。