浅析JS内存 二

讲解一下执行上下文/调用堆栈/内存栈

<script>
  var a = 1;
  function say() {
    var c = 4
    console.log(c)<br>  
console.log(a)<br>  
var d = 5 } console.log(b)<br> console.log(a) say() var b = 2; </script>

 1、在v8引擎加载这段代码

 2、引擎解析代码,创建一个 全局执行上下文(调用堆栈、内存栈)

    

 3、解析代码,将全局的所有变量、声明函数添加到全局执行上下文的内存栈中。这里会将 变量a 和 变量b 函数say 添加到内存栈中。所有的变量和函数都会添加进去开始执行的样子:

    

     (其中 a、b 变为undefined 涉及了变量提升)

4、 将全局的执行方法,都push到调用堆栈中

   步骤1:

     执行到 console.log(b)这一步的时候,全局执行上下文样子

   

       这里打印 b 是 undefined

  结束完成之后,console.log(a) 会被弹出栈。

        

   步骤 2 :

      console.log(b) 执行完成后,会直接 pop 弹出 调用堆栈。

      调用 console.log(a) , 在console.log(b) 到 console.log(a) 并未有任何赋值操作。

    所以内存栈中未有任何变化。

    但是调用堆栈里面会有变化,在这里面console.log(b)已经执行完成,会被 pop 推出栈,然后到了console.log(a),试图样子:

         

       这里打印 a 是 1

  结束完成之后,console.log(a) 会被弹出栈。

   步骤 3:

  调用 say() 函数,将 say() push 的调用堆栈中。

  创建一个新的 say 的执行上下文。

   

       这里为 say 重新创建了一个 执行上下文 。并且将它内部的 变量和函数推入它对应的 内存栈 中。将 c : 4 , d : 5 推到 内存栈中。

      这里堆栈一次执行 console.log(c) , console.log(d) (图中错把 d写作 a)

步骤 5 :

  当 say () 执行完毕后,回收内存栈已经调用栈。

  完成!!

前端 javascript的 堆栈理解 

     在理解这些时候,我们可以先看下 值类型 和 引用类型,值类型 和 引用类型 的存储方式来区分前端的堆栈。

      值类型/原始类型 : undefined 、null 、number 、string 、boolean

      引用类型/堆类型 : object 、function 、array 

    值类型 :

    保存在内存栈中,分配固定的空间,所以保存的值是不可变的。

    js 代码执行的或者某个方法执行的时候,都会有自己独立的执行上下文,其中包括内存栈和调用栈,该执行上下文中定义的值类型就会保存在该内存栈中。

    当该方法执行结束,这个内存栈就会销毁,值类型也随之移除

  

   值类型的特点:

      1、任何方法都无法改变值类型的   (??不太理解了)

           2、相同类型的值类型的比较是它们值的比较        

      3、值类型都存放在内存栈中

           4、保存的是值本身的值,不是指向的地址。

   引用类型:

       值保存在堆内存中,占用的空间也不固定,所以保存的值是可以变的

  当我们创建一个对象的时候,我们会将该对象保存在运行的内存堆中,以便与反复利用。

  当被某一个变量引用的时候,会给变量该内存堆中的指定引用对象的地址,并且把该变量中包含的引用对象的地址保存在内存栈中,

  当引用该变量所在的方法或者是执行上下文执行结束的时候,并不会销毁,只有在没有被任何引用的时候,该对象才会被销毁。

  这里的这种销毁方法就是垃圾回收中的一种,叫做标记回收

  标记回收( 以对象为例,当这个对象每被引用一次,就在该对象的标记上面 +1 ,当某一个引用该对象的变量不引用了就 -1 ,当

  标记为 0 的时候,被系统检测到之后,就会销毁。 )

   引用类型的特点:

         1、引用类型的值是可变的

         2、引用类型在内存栈中保存对象地址,在堆内存中保存对象的本身

         3、引用类型的比较(===),是比较它们保存的对象的堆内存地址

        4、引用类型的赋值,当给某一个变量复制的时候,实际是将该对象的堆内存地址复制给变量

未完,待续......
原文地址:https://www.cnblogs.com/zhishiyv/p/12105296.html