我读过一些关于 V8 的文章。然而,我仍然有一个疑问:

据我所知,在 V8 JavaScript 引擎中:原始值(如数字和字符串)和对对象的引用始终存储在堆栈中,而对象(包括数组和函数)始终存储在堆中,但是当(对对象或原始值的引用)是另一个对象的属性时,它(对对象或原始值的引用)存储在堆中以使对象属性结合在一起。

例如 :

  let name ="Tom"; // name is stored in the stack
    let test ={name :"Tom", age:44}; // name and age are stored in the heap and test (the reference to the object) is stored in the stack
    let temp ={t1:test}; // t1 is stored in the heap and temp (the reference to the object) is stored in the stack

文章是关于形状(又名隐藏类)的,并且有该代码

const point = {};
point.x = 4;
point.y = 5;
point.z = 6;

文章中有一张照片展示了该物体(point)在记忆中的样子:

我认为这张照片仅代表(包含)堆上的部分(换句话说:这张照片不代表(包含)对对象的引用,(point)并且该引用存储在堆栈中),因此照片必须是这样的:

所以我的问题是:我的想法正确吗(换句话说:我的照片正确吗?)?

1

  • 不知道 JS 内部的确切情况,但有一些逻辑观察。 let name ="Tom"; 我会说name引用存储在堆栈上,但字节Tom存储在堆上。我这样说是因为 JS 中的字符串可能很大,否则很容易吞噬堆栈。还要注意{age: 44}这里的 age 是一个属性而不是变量,因此出于与字符串和有限堆栈大小相同的原因,再次放在堆上是有意义的。换句话说:简单地说,当需要有限的内存需求(如var's和 var)时,将使用堆栈。references


    – 


最佳答案
1

在 V8 JavaScript 引擎中:原始值(如数字和字符串)和对对象的引用始终存储在堆栈中

不,这是不正确的。(有关更多详细信息,请参见。)

我认为这张照片只代表(包含)堆上的部分

是的。(请注意,您实际上可以看到堆上的原语,这驳斥了您的初始前提。)

12

  • 链接的答案完全说得通,GC 和作用域使得除了函数堆栈之外的任何用途几乎都无法使用堆栈。我在上面的评论中确实对此感到疑惑,您可能出于性能原因而期望函数闭包中的无作用域变量使用堆栈,但我认为收益不值得这么复杂。也许 V8 涡轮风扇阶段可以缓解这种情况。


    – 

  • @jmrk 我的照片正确吗(第二张照片)?


    – 

  • 1
    @f877576 有时是准确的:引用可以在堆栈上。它也可以位于堆上。


    – 

  • 1
    @f877576 V8 确实总是使用堆栈(这就是计算机的工作方式),但并非每个引用都在堆栈上。堆上有很多引用:具有指向其他对象的属性的对象。甚至不是每个局部变量都是堆栈分配的。根据经验法则,堆栈用于 (1) 当前函数需要的东西(2) 其他任何东西都不需要的东西以及(3) 足够小的东西。


    – 

  • 1
    @f877576 一般来说,所有内容都存储在堆中(包括对象引用,就像其他所有内容一样),只有极少数例外(例如某些条件下的局部变量),其中少数几个内容可以存储在堆栈中作为优化。


    –