值能否在不分配内存的情况下存储?

3

我一直在这里阅读

https://developer.mozilla.org/en-US/docs/JavaScript/Memory_Management#Allocation_via_function_calls

而这些行让我有点困惑:

var s = "azerty";
var s2 = s.substr(0, 3); // s2 is a new string
// Since strings are immutable value, JavaScript may decide 
// to not allocate memory, but just store the [0, 3] range.

据评论所说,JavaScript 可能决定不分配内存,而只是存储范围 [0,3]。现在,在存储之前难道不必分配内存吗?如果真是这样,那么究竟会发生什么,使得存储的范围被存储在未被其他值占用的空闲空间中?
2个回答

3
这段注释的意思是,s2 不必专门为三个字符 "aze" 分配内存。相反,它可以使用已经由 s 分配的用于 "azerty" 的内存,并记住自己的长度仅为三个字符。
不可变性部分也很重要:如果 s 不是不可变的,则可以决定将其值从 "azerty" 更改为 "foobar" 而不告诉任何人,从而间接地更改 s2 的值为 "foo" -- 这将是灾难性的。
当然,这并不意味着完全没有内存会被分配;我们仍然需要分配内存来存储字符串内容的位置以及字符串的长度。

澄清一下:它确实需要为描述“取另一个字符串的字符0-3”的(内部)对象分配内存。 - Joachim Sauer
这种做法并不特别聪明。如果原始字符串变得可以进行垃圾回收(但新字符串不行),会发生什么? - NullUserException
2
@NullUserException: 它不会被垃圾回收。只要字符串变量中的任何一个存在,所有字符串数据将一直保留在内存中。 - Guffa
2
@Guffa 没错。现在假设s1是一个非常长的字符串,而s2被定义为这个长字符串的一个短“范围”。使用这种方案,只要s2存在,你就无法对s1进行垃圾回收。 - NullUserException
@NullUserException:每种方法都有优点和缺点(例如,以这种方式获取长期值的短期子字符串要便宜得多)。我相信JS引擎人员会广泛使用流行应用程序和库中的分析信息以及野外代码来决定是否采用这种做法能够提供整体利益。 - Jon

2
这段评论讨论了为字符串的字符数据分配空间的问题。
当你创建一个新变量时,自然需要为它分配空间,但这不一定是像堆上的新对象那样,它可以是预先分配的变量数组中的一个项目。
两个变量指向相同的字符数据的好处是,即使子字符串的长度很长,获取子字符串也使用非常少的内存。缺点是原始字符串将在任何从它中使用的子字符串存在期间仍然保留在内存中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接