JS中的调用堆栈

346 阅读3分钟

1.js的调用堆栈,遵循原则(FILO,即first in last out,先进后出)

上代码

//声明
var a = function(){
    function b(){
        function c(){
            console.log('winki is a handsome boy')            
        }
    }
}

//调用
a()

栈(stack)

此时堆栈中的内容是这样的(可以理解为苹果手机就是栈)
入栈

出栈

堆(heap)

局部变量,长度固定的的值放在堆中。比如:

//声明
var a = function(){
    function b(){
        function c(){
            console.log('winki is a handsome boy')            
        }
    }
}

//调用
a()

'winki is a handsome boy' 是一个固定长度的字符串,它就放在堆中(可以理解为安卓手机就是栈)

这样一来,我们就可以理解为
局部变量,固定长度,对象的实例这些放在堆(heap)中
引用变量,对象的引用这些放在栈中(stack)


调用堆栈:(另一个理解版本)

理解调用堆栈,首先理解几个比较重要的知识点

  1. JavaScript是单线程的

    1. 单线程:什么是线程?
      1. 我们可以这么理解:线程是比进程更小的计算单位。一个小时由60分钟组成,一个小时我们可以看成进程,一分钟我们可以看成一个线程。对于java那些高级面向对象的,它们是多线程的,它们可以同一时间执行多个任务(虽然本质上还是单线程),而对于JavaScript来事,是单线程的,同一时间只能执行一个任务。
  2. 单线程任务执行顺序遵循FILO规则(first in last out,即先进后出的特点)

    1. 我们用一张图看单线程执行任务的顺序
  3. 理解什么是栈
    栈:我们理解为钥匙key。key可以去打开指定的room,比较小的东西,固定的一般都可以当作key

  4. 理解什么是堆
    堆:我们理解为room。room一般放的都是不确定大小的东西,拥有key就可以打开指定的room,room同时大小也是不固定的。可能这个room本来就这么大,但是它只放了一些东西。

上下文(容器)

  1. 首先我们先知道上下文是什么,上下文我们可以理解为一个容器,每个函数、变量都是在里面活动的。

  2. 上下文有两个阶段:创建阶段、执行阶段。

  3. 我们理解这两个阶段中,各自做了什么事情。

  4. 创建阶段:

    1. this值的决定,即This值的绑定

      • 全局执行上下文:this一般指向全局对象(在浏览器中,this指向window)

      • 函数执行上下文:this指向的是调用它的对象。没有用var声明,也没有对象调用它的函数,默认的this指向window。如下:

        let zoo = {
            animal:function(){
                console.log(this)
            }
        }
        zoo();	//此刻的this指向window
        let dog = zoo.animal;
        dog();	//此刻的this指向zoo
        
    2. 创建词法环境组件

      1. 环境记录器:存储着变量和函数声明的实际位置。
      2. 外部环境的引用:它可以访问父级词法环境(作用域)
    3. 创建变量环境组件

      1. 变量环境也是一个词法环境,所以它有着上面词法环境的所有属性。

      2. 它的环境记录器:记录着声明变量和绑定的执行上下文的关系

      3. 在ES6中,词法环境和变量环境的不同在于:前者用来存储函数和变量声明(let 和 const 绑定),

        后者 只存储var 绑定。

  5. 执行阶段:变量分配,执行代码。