(我是一名V8开发者。)
总体而言:字符串在Web上非常常见,因此JavaScript引擎会为许多不同的字符串操作实现许多不同的优化,因此现代JS引擎中的字符串处理系统往往非常复杂。不过,在这方面我们可以专注于“简单”的字符串。
一个单独字符将占用2个字节。
事实上还有更多内容:V8内部区分单字节和双字节字符串。当给定字符串中的所有字符都可以用一个字节来表示时,V8通常会采用这种形式。
浅大小和保留大小都是16个字节。为什么?
评论者已经发布了有关“浅层大小”和“保留大小”之间差异的描述链接,所以我不会涉及到那点。对于简单的字符串,它们的大小永远是相同的。
堆上的所有对象都以形状描述符开始,该描述符占用一个指针大小(这些天通常为4个字节,由于在64位平台上的“指针压缩”)。
字符串还在其对象头中额外存储了两个4个字节的字段:字符串的哈希值(经常需要使用,因此为避免每次都要重新计算,它被缓存在那里),以及字符串的长度。
此后,它们会存储实际字符。任何堆对象的大小必须是指针大小的倍数,即4的倍数,因此字符串的大小将向上舍入;最后几个字节可能未被使用。
因此,简单ASCII字符数为n
的字符串的大小为:
12 + 4 * Math.ceil(n/4)
这可能会随时间而改变,如果在构建时关闭了指针压缩,则会有所不同;如果字符串中有双字节字符,则会有所不同;如果字符串是“切片”或“cons”字符串,则会有所不同;如果字符串与Blink共享,则会有所不同。我可能还忘记了一些其他情况,也会导致结果不同。
如果你稍微扩展一下你的实验,你会发现:
""
占用 12 字节
"1"
到 "1234"
占用 16 字节
"12345"
到 "12345678"
占用 20 字节
"123456789"
占用 24 字节,依此类推。