JavaScript中字符串与数组的内存消耗及Blob相关疑问
JavaScript字符串与数组的内存占用疑问
一、字符串:Blob.size与UTF-16内存占用的差异
new Blob(['a']).size返回1字节,但JavaScript字符串在引擎内部采用UTF-16编码(单个字符最少占2字节),两者的差异源于存储层面与序列化层面的编码逻辑不同:
- JS引擎内部为高效处理Unicode字符,使用UTF-16存储字符串,因此单个ASCII字符在内存中确实占用2字节。
- Blob的核心作用是将内容序列化为可传输的二进制数据,默认会把字符串编码为UTF-8。对于ASCII字符(如'a'),UTF-8仅需1字节,因此
Blob.size返回的是UTF-8编码后的字节数,而非JS内存中的实际存储大小。
二、数组:Blob.size不符合预期的两个疑问
基础代码与现象
执行以下代码后,new Blob(changes).size返回79800,而非预期的40000(200×200个Uint8Array(1)的总字节数):
const x = 200; const y = 200; const changes = [] for (let i=0;i<y;i++) { let subArr = [] for (let j=0;j<x;j++) { subArr[j]= new Uint8Array(1) } changes[i]=subArr } console.log(new Blob(changes).size)
疑问1:为何实际大小接近预期的两倍?
这个现象的核心原因是Blob处理嵌套数组与TypedArray时的内存对齐逻辑:
当你将二维数组(每个子元素是Uint8Array(1))传给Blob时,Blob会递归展开所有元素并拼接二进制内容。在部分浏览器的实现中,每个子数组的第一个Uint8Array(1)会被正常读取1字节内容,但后续的每个Uint8Array会因为内存对齐机制,被自动填充为2字节(即使它本身仅包含1字节数据)。
计算下来:每个子数组的总大小为1 + 199×2 = 399字节;200个子数组的总大小就是399×200 = 79800,与实际结果完全匹配。
疑问2:填充同一个Uint8Array对象,为何Blob.size仍为79800?
改用以下代码填充数组后,结果依然为79800:
for (let i=0;i<y;i++) { changes[i] = new Array(x).fill(new Uint8Array(1)) }
原因在于Blob构造函数的遍历逻辑:无论传入的BlobPart是否为同一对象,都会读取其内容并添加到Blob中。也就是说,这个唯一的Uint8Array会被Blob读取40000次,每次读取的行为和之前的独立对象一致——每个子数组的第一次读取是1字节,后续199次读取被填充为2字节,最终总大小依然是79800。
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

