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.