Here the JavaScript engine encounters a problem: the array countains two different types of data, numbers and strings.

We want to store a reference to a string in the array. A reference is just a memory location (where the actual characters of the string are). A memory location is just a number. You can think of you system memory as huge array, where the reference is an array index.

So a string reference is a number, and a number is also a number. How can we tell which is which?

The answer is called a "boxed value". We wrap each number in an object and store the object reference in the array. Now each array element can be a reference.

For each number in the array we now have to store two things:

reference to the object (8 bytes)

the boxed number object (16 bytes)

Why is the number object 16 bytes large? First, it needs to store the number value itself (that 64-bit floating point value). Each JavaScript object also has an internal type called a "hidden class", which is another reference value.

Why does it take 8 bytes to store a reference? Remember how system memory is like an array? If you have a 32 bit address you can represent array indices up to 2^32. If you store one byte at each array index you can then address up to 2^32/(1024*1024*1024)=4GB of memory. Since most computers today have more than 4GB of memory you need to go one step further to 64 bit addresses (8 bytes per address).

The above is more of a common sense explanation, I'm pretty sure there's more nuance to this.