How large is a Buffer?
The gzip()
and gzipSync()
functions in the zlib return a result of type Buffer
. How do you calculate the size of the result? I came across two properties of the Buffer
type: length
and byteLength
. Is there a difference? The API documentation for Buffer
does not tell you, because it lacks the length
and byteLength
properties. Where do these properties come from? Likely from the prototype.
In search of a prototype
Let’s find Buffer
’s prototype. The Node.js documentation says the type Buffer
is a subclass of Uint8Array
. What is Uint8Array
? The JavaScript standard says Uint8Array
is a TypedArray
. The TypedArray
prototype defines length
and byteLength
. We’ve finally found where length
and byteLength
come from!
Let’s take a look at what they mean.
Bytes and array elements
According to the documentation, length
is the number of elements in a TypedArray
and byteLength
is the number of bytes that the elements occupy.
Since a Buffer
is a Uint8Array
, to know whether length
and byteLength
are different for a Buffer
, we need to know whether they are different for an Uint8Array
.
Let’s do some math. 1 byte is another way of saying 8 bits. An Uint8Array
is an array of unsigned 8-bit integers, so every element of the Uint8Array
takes 8 bits, or 1 byte. So for an Uint8Array
the number of elements is the same as the number of bytes, and so byteLength
is the same as length
. Since a Buffer
is also an UInt8Array
, it makes no difference whether you use length
or byteLength
.
length
versus byteLength
If byteLength
and length
are the same, why are they two separate properties? byteLength
and length
are defined for everything with the TypedArray
prototype. Some objects with the TypedArray
prototype store elements larger than 1 byte, for example Int16Array
(2 bytes) or Float64Array
(8 bytes). For these objects, byteLength !== length
. It’s an inconvenient of inheritance: Buffer
ends up with superfluous properties because other objects with the same prototype need them.