Hai*_*iri 4 javascript memory-management
我读到每个函数都有自己的堆栈,这意味着当函数结束时,它的变量不再保留在内存中.我还读到对象是通过引用返回的.
考虑这个例子:
function getObject() {
var obj = {name: "someName"};
return obj;
} //At the end the locals should disappear
var newObj = getObject();// Get reference to something that is no longer kept in the stack,
console.log(newObj);//Run Code Online (Sandbox Code Playgroud)
因此,如果函数返回的值是对 不再存在的对象的引用(在堆栈中),我们如何仍然获得正确的值?在C(语言)中返回指向局部变量的指针是疯狂的.
首先,快速免责声明:现代JavaScript引擎实际执行的理论和优化过程之间存在差异.
让我们从理论开始:
该对象不在堆栈上,只是包含对象引用的变量.该对象单独存在,并在堆中创建.所以在你的例子中,就在函数返回之前,我们在内存中有这个:
+??????????????????+
| (object) |
+??????????????????+
[obj:Ref11254]?????>| name: "someName" |
+??????????????????+
obj,变量,包含对象的引用(Ref11254当然,这只是一个概念性的数字,我们实际上从未看到过这些).当函数返回时,返回obj(Ref11254)的内容,(obj变量)与堆栈的其余部分一起消失.但是,只要某个东西有引用的对象(在你的情况下就是newObj变量),它就会一直存在.
在实践中:
作为优化,现代JavaScript引擎经常在堆栈上分配对象(受特定于引擎的大小限制).然后,如果在函数终止并清理堆栈后对象将继续存在,则将它们复制到堆中.但是如果对象不能存活(也就是说,没有保留或正在返回它的引用),他们可以让它与堆栈一起清理.(为什么?因为堆栈分配和清理非常快,而且许多对象仅在函数本地使用.)
值得一提的是,同样的问题出现了变数,如果函数创建一个函数:
function getFunction() {
var x = 0;
return function() {
return x++;
};
}
var f = getFunction();
console.log(f()); // 0
console.log(f()); // 1
console.log(f()); // 2Run Code Online (Sandbox Code Playgroud)
现在不只是函数getFunction返回(它是一个对象)幸存下来,但它也是如此x!即使变量"在堆栈上",并且堆栈在getFunction返回时被回收.怎么可能?!
答案是,从概念上讲,局部变量不在堆栈中.将它们放在堆栈上是一种优化(常见的).从概念上讲,局部变量(以及其他一些东西)存储在一个名为LexicalEnvironment对象的对象中,该对象是为调用而创建的getFunction.从概念上讲,函数getFunction返回有一个对LexicalEnvironment对象的引用,因此它(以及它包含的变量)即使在getFunction返回后也会继续存在.(函数getFunction返回称为闭包,因为它关闭了创建它的环境.)
当然,在实践中,现代JavaScript引擎并不能真正做到这一点.它们在堆栈上创建变量,可以快速轻松地清理它们.但是如果一个变量需要继续存在(比如x我们上面的示例中的需求),引擎会将它(以及它需要保留的任何其他变量)放入堆中的容器中并且闭包引用容器.
更多关于这个问题的答案和我贫穷的小博客 (使用稍微过时的术语)的闭包.