在Javascript中,什么情况是使用的是堆,什么情况使用的是栈?

leohxj
  • 677

我的理解是new操作的肯定是在栈中,函数和变量的声明在堆中,但是如何验证我的假设?

实际情况又是怎样,我们编码的时候需要注意些什么?

回复
阅读 5k
2 个回答
Humphry
  • 16.4k
✓ 已被采纳

对JavaScript我们需要区分标准(ECMAScript)与实现(浏览器):标准里没有对变量如何存储进行限定,仅仅是描述了行为;而实现里则自顾自的实现,只要符合描述的行为即可。

标准里这些行为跟存储方式相关:

  1. Execution Contexts,执行上下文,变幻多端的this在这个概念里确定。
    这个概念基于stack,存储的是对上下文——LexicalEnvironment、VariableEnvironment、thisBinding——的一层封装。
  2. Lexical Environments,词法作用域,涉及到基于作用域链的寻址问题。
    这个特性很难用栈来实现,标准从来没有提到怎样存储。

JavaScript或者类似于JavaScript的脚本语言,都不会留有让你直接操作内存的空间。没有指针,而都用了“引用”、“共享”之类的概念进行了封装。因而JavaScript中堆栈的概念被模糊了,更加重要的还是标准里面定义的行为。


怎么证明一个语言的一个特性是用了堆还是用了栈?由于JavaScript里面不包含对内存地址的直接描述,因此你很难追寻生命周期与内存地址的关系。

用反证可以去掉一些可能性。比如,验证“函数内变量的生命周期与函数执行生命周期的关系”,可以用闭包式的变量引用进行反证:

function a(){
    var x = 1 ;
    function b(){
        alert(x) ;
    }
    return b;
}
var c = a();
c();
// return 1
// a()执行结束以后x依然存在,变量生命周期长于函数执行生命周期,无法简单地用栈来实现
王子亭
  • 11.5k

取决于引擎的实现,见:http://stackoverflow.com/questions/6602864/stack-and-heap-in-v8-javascript

首先对象因为总是传递引用,所以生命周期是非常复杂的(因为有闭包,函数执行完成后对象不一定会被销毁),因此个人认为对象很难放到栈上,至于基本类型(数字和字符串)倒是有可能放在栈上,有关 V8 的具体实现见上面的链接。

宣传栏