zoukankan      html  css  js  c++  java
  • 浅析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、引用类型的赋值,当给某一个变量复制的时候,实际是将该对象的堆内存地址复制给变量

    未完,待续......
  • 相关阅读:
    TypeScript入门( 一)
    PureComponent: setState未触发render渲染
    再次了解深浅拷贝问题
    关于wepack2.0报错问题
    ES7及ES8的新特性
    闭包
    setState是异步还是同步?
    SQL注入测试之DVWA环境
    i春秋实验--struts2远程命令执行S2-045漏洞利用与修复
    i春秋实验--IIS写权限漏洞利用
  • 原文地址:https://www.cnblogs.com/zhishiyv/p/12105296.html
Copyright © 2011-2022 走看看