Javascript 在哪里为函数调用的结果分配内存?栈还是堆?
Where does Javascript allocate memory for the result of a function call? Stack or heap?
我在网上找遍了,似乎找不到这个问题的答案。
我读到栈是用来存储基元的,堆是用来存储对象的。
我还读到堆栈的大小是固定的,一旦分配它就不会改变,这就是为什么它用于原语,因为 JS 在运行前就知道每个变量的大小。
我也知道基元是不可变的,所以如果我们尝试重新分配一个变量,它不会改变它内存地址的值,而是会在内存中分配新的space,存储新值并将其地址分配给变量。
如果以上是正确的,那么当我这样做时会发生什么?
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.repeat(10000000000)
如果堆栈不能增长,是否意味着在某些时候我会因为变量太大而导致堆栈溢出?
谢谢。
答案可能因引擎而异,这对您的代码来说真的无关紧要。担心运行出栈if/when你运行 出栈。 JavaScript 的规范不要求实现做一件事或另一件事。它描述的是行为,而不是该行为的实现。
但实际上来说:JavaScript 引擎似乎不太可能尝试将大量字符串放入堆栈。更有可能的是,它会将其放入堆中。这并不意味着它不能将 other 字符串放入堆栈。也许它根据大小决定。也许它是根据生命周期来决定的——也许它会把一个只在函数中局部使用的小字符串放在堆栈上,但是把一个很大的字符串,或者一个全局保留的字符串放在堆上。
重点是:现代 JavaScript 引擎很复杂,而且高度、高度优化。他们不太可能采取如此简单的观点,如“基元在堆栈上,对象在堆上。”
I read that the stack is used to store primitives and heap is for objects.
不一定。对象也可以在堆栈上分配,并且在历史的不同时期至少有一些 JavaScript 引擎。如果一个对象在函数调用结束后无法存活,并且不是很大,将它放在堆栈上可以在函数 returns 死掉时轻松回收它。
I also know that primitives are immutable, so if we try to reassign a variable, it will not change the value at its memory address but will rather allocate new space in memory, store the new value and assign its address to the variable.
不用太深入理论,这也很可能是特定于实现的。考虑 a = 1
。我们无法判断这是将值 1
放入与 a
关联的内存中,还是将对表示 1
的不可变单例的引用放入 a
中。前者似乎比后者更很多(对于数字;字符串是另一回事),但我们不知道也不可能知道(在一般情况下;我们可以对于特定引擎的特定版本),因为它对我们的代码没有影响,并且规范不需要一种行为或另一种行为。
我在网上找遍了,似乎找不到这个问题的答案。
我读到栈是用来存储基元的,堆是用来存储对象的。
我还读到堆栈的大小是固定的,一旦分配它就不会改变,这就是为什么它用于原语,因为 JS 在运行前就知道每个变量的大小。
我也知道基元是不可变的,所以如果我们尝试重新分配一个变量,它不会改变它内存地址的值,而是会在内存中分配新的space,存储新值并将其地址分配给变量。
如果以上是正确的,那么当我这样做时会发生什么?
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.repeat(10000000000)
如果堆栈不能增长,是否意味着在某些时候我会因为变量太大而导致堆栈溢出?
谢谢。
答案可能因引擎而异,这对您的代码来说真的无关紧要。担心运行出栈if/when你运行 出栈。 JavaScript 的规范不要求实现做一件事或另一件事。它描述的是行为,而不是该行为的实现。
但实际上来说:JavaScript 引擎似乎不太可能尝试将大量字符串放入堆栈。更有可能的是,它会将其放入堆中。这并不意味着它不能将 other 字符串放入堆栈。也许它根据大小决定。也许它是根据生命周期来决定的——也许它会把一个只在函数中局部使用的小字符串放在堆栈上,但是把一个很大的字符串,或者一个全局保留的字符串放在堆上。
重点是:现代 JavaScript 引擎很复杂,而且高度、高度优化。他们不太可能采取如此简单的观点,如“基元在堆栈上,对象在堆上。”
I read that the stack is used to store primitives and heap is for objects.
不一定。对象也可以在堆栈上分配,并且在历史的不同时期至少有一些 JavaScript 引擎。如果一个对象在函数调用结束后无法存活,并且不是很大,将它放在堆栈上可以在函数 returns 死掉时轻松回收它。
I also know that primitives are immutable, so if we try to reassign a variable, it will not change the value at its memory address but will rather allocate new space in memory, store the new value and assign its address to the variable.
不用太深入理论,这也很可能是特定于实现的。考虑 a = 1
。我们无法判断这是将值 1
放入与 a
关联的内存中,还是将对表示 1
的不可变单例的引用放入 a
中。前者似乎比后者更很多(对于数字;字符串是另一回事),但我们不知道也不可能知道(在一般情况下;我们可以对于特定引擎的特定版本),因为它对我们的代码没有影响,并且规范不需要一种行为或另一种行为。