是Javascript子字符串虚拟的

Is Javascript substring virtual?

本文关键字:虚拟 字符串 Javascript      更新时间:2024-06-29

如果我们有一个名为str1的巨大字符串,比如500万个字符长,然后是str2 = str1.substr(5555, 100),那么str2是100个字符长的,并且是从5555(或任何其他随机选择的位置)开始的str1的子字符串。

JavaScript如何在内部存储str2?是复制了字符串内容,还是新字符串有点虚拟,只存储了对原始字符串的引用以及位置和大小的值?

我知道这取决于实现,ECMAScript标准(可能)没有定义字符串实现的底层。但我想从一些从内部了解V8或SpiderMonkey的专家那里了解这一点。

感谢

AFAIK V8有四种字符串表示:

  1. ASCII
  2. UTF-16
  3. 多个字符串的串联
  4. 另一个字符串的切片

在substrings和RegExps的土地上的冒险有很好的解释和插图。

因此,它不必复制字符串;它只需要对另一个字符串使用开始和结束标记。

蜘蛛猴也做同样的事情。(请参阅Firefox中的大型子字符串比Chrome快~9000倍:为什么?…尽管Chrome的答案已经过时了。)

这可以真正提高速度,但有时这是不可取的,因为它会导致小字符串占用较大父字符串的内存(V8错误报告)

我的这篇旧博客文章解释了它,以及其他一些字符串表示形式:https://web.archive.org/web/20170607033600/http://blog.cdleary.com:80/2012/01/string-spidermonkey/中的表示

搜索";依赖字符串";。我想我知道你可能会对这个问题有什么看法:它们有时可能是有问题的东西,因为如果没有对原始字符串的引用,你可以保留一个巨大的字符串,以便保留一个语义上可以访问的小字符串。实现可以做一些事情来缓解这个问题,比如在GC生成的基础上记录信息,看看是否存在这样一个依赖字符串的实体,并将它们折叠到最小大小,但据我所知,这还没有完成。(本质上,使用这种方法可以在GC扫描时恢复runtime_refcount == 1样式的信息。)