Javascript在哪里为函数调用的结果分配内存?堆叠还是堆积?

Javascript在哪里为函数调用的结果分配内存?堆叠还是堆积?,javascript,memory-management,garbage-collection,heap-memory,Javascript,Memory Management,Garbage Collection,Heap Memory,我在互联网上找遍了,似乎找不到这个问题的答案 我读到堆栈用于存储原语,而堆用于对象 我还了解到,堆栈的大小是固定的,一旦分配,它就不会改变,因此它被用于原语,因为JS在运行前知道每个变量的大小 我还知道原语是不可变的,因此如果我们尝试重新分配变量,它不会更改其内存地址的值,而是会在内存中分配新空间,存储新值并将其地址分配给变量 如果以上是正确的,那么当我这样做时会发生什么 let string = "Hello World"; // Memory allocated

我在互联网上找遍了,似乎找不到这个问题的答案

  • 我读到堆栈用于存储原语,而堆用于对象

  • 我还了解到,堆栈的大小是固定的,一旦分配,它就不会改变,因此它被用于原语,因为JS在运行前知道每个变量的大小

  • 我还知道原语是不可变的,因此如果我们尝试重新分配变量,它不会更改其内存地址的值,而是会在内存中分配新空间,存储新值并将其地址分配给变量

如果以上是正确的,那么当我这样做时会发生什么

let string = "Hello World"; // Memory allocated for "Hello World"
string = string.ToUpperCase(); // New memory allocated for "HELLO WORLD"
HELLO WORLD的新内存在哪里分配?它在堆栈中是因为它是原语吗?或者它在堆中是因为JS在运行代码之前不知道它的值

如果它在堆栈中,那么旧的“Hello World”会发生什么?由于只有堆被垃圾收集,这是否意味着旧的、未使用的字符串将一直保留在那里,直到程序完成运行

如果我这样做会怎么样

string=string。重复(1000000000)

如果堆栈不能增长,这是否意味着在某个时候我可以因为变量太大而导致堆栈溢出


谢谢。

答案可能因引擎而异,这对您的代码并不重要。如果堆栈用完,请担心堆栈用完。JavaScript的规范不要求实现做一件事或另一件事。它描述行为,而不是该行为的实现

但实际上:JavaScript引擎似乎不太可能尝试在堆栈上放置大量字符串。更有可能的是,它会把它放在堆里。这并不意味着它不能在堆栈上放置其他字符串。也许它是根据大小来决定的。也许它是根据生命周期来决定的——也许它会将一个只在堆栈上的函数中本地使用的小字符串放在堆栈上,但会将一个大字符串或一个全局保留的字符串放在堆上

关键是:现代JavaScript引擎非常复杂,而且高度优化。他们不太可能采取“原语放在堆栈上,对象放在堆上”这样一种过于简单的观点

我读到堆栈用于存储原语,而堆用于对象

不一定。对象也可以在堆栈上分配,并且至少在历史上的不同时期被一些JavaScript引擎分配过。如果一个对象在函数调用结束后无法生存,并且不是大型对象,那么将其放在堆栈上可以在函数返回时轻松回收它

我还知道原语是不可变的,因此如果我们尝试重新分配变量,它不会更改其内存地址的值,而是会在内存中分配新空间,存储新值并将其地址分配给变量


在不深入理论的情况下,这很可能是特定于实现的。考虑<代码> a=1 < /代码>。我们无法判断这是将值
1
放入与
a
相关联的内存中,还是将对表示
1
的不可变单例的引用放入
a
中。前者似乎比后者更有可能(对于数字;字符串是另一回事),但我们不知道也不可能知道(在一般情况下,对于特定引擎的特定版本,我们可以知道),因为它对我们的代码没有影响,规范也不需要一种或另一种行为。

既没有堆栈也没有堆。调用堆栈(可以同时有多个)将始终具有固定大小的值(并非所有大小都相同),因为在访问变量时,您希望能够轻松地计算内存位置(您不希望在堆栈中搜索每个值)。对于数字来说,将它们放入堆栈很容易(64位大小,可能更小),对于字符串来说就不容易了,因为它们的大小通常是未知的。如果引擎静态地知道堆栈的大小,它就可以将其放入堆栈中。理论上也可以使用不断增长的堆栈,但通常不需要这样做,在无限递归的情况下,提前崩溃程序比在计算机内存耗尽之前运行程序更有意义。这就是为什么调用堆栈通常是固定大小的。谢谢您的回复。对不起,我不明白你说的“既没有堆栈也没有堆”是什么意思。。。事实上,你在最后一句话中写道“可以把它放好”,这让我觉得引擎可以采取不同的行动,这取决于与t-j-crowder在回答中所写内容相匹配的具体情况。谢谢大家!@EccTama-可以有多个堆栈和多个堆,所以“the”应该是“a”。谢谢您的回复!我不知道引擎可以根据具体情况以不同的方式“决定”处理相同类型的值。大多数在线资源只是将其划分为primitives=stack,non-primitives=heap,在阅读了您的答案后,感觉有点太简单了。现在有点道理了。非常感谢。