阅读 89

JS的编译、执行、调用栈、栈溢出

js代码的执行流程:编译----> 执行。

一、案例一

例如:

var myname ='极客时间';
function showName() {
    console.log('函数showName被执行');
}
showName();
复制代码

这段代码在执行前会先编译。

编译的过程:

  • 创建一个该段代码对应的执行上下文,执行上下文有变量环境、词法环境。

  • 从上而下的开始编译。

  • 当遇到声明时,比如myname的声明,会将myname添加到变量环境中,值为undefined。

  • 当遇到函数showName时,将整个函数放到堆中,showName放入变量环境中,showName的地址指向堆中的地址。

执行过程:

  • 执行var myname ='极客时间'时,对变量环境中myname进行赋值。

  • 执行到showName时,从变量环境总进行查找,找到showName函数时执行。

二、案例二

var a = 2
function add(b,c){
  return b+c
}
function addAll(b,c){
    var d = 10,
    result = add(b,c)
    return  a+result+d
}
addAll(3,6)
复制代码

编译过程:

  • 创建一个全局上下文,加入a=undefined,function add(b, c){......},function addAll(b, c){......},全局执行上下文入调用栈。

执行过程:

  • 执行到var a =2时,从全局执行上下文的变量环境中查找a,找到后,赋值为2。

  • 调用addAll函数时,对addAll函数进行编译,创建addAll的执行上下文,b、c、d、result为undefined,并加入addAll的执行上下文的变量环境中。

  • 执行addAll函数,发现调用了add函数。

  • 编译add函数,创建add函数的执行上下文,b、c为undefined,并加入到add函数的执行上下文的变量环境中,add函数的执行上下文入栈。

  • 执行add函数,执行完,add函数的上下文出栈。

  • 继续执行addAll函数,执行完上下文出栈。

  • 全局上下文出栈。

                                                     例子2的调用栈

调用栈是有大小的,超出大小就会报栈溢出的错误。

三、案例三

es6之前,作用域只有全局作用域、函数作用域,es6新加入了块级作用域。块级作用域中定义的变量不会有变量提升,在外部不能被访问到。

 function foo(){
    var a = 1
    let b = 2
    {
      let b = 3
      var c = 4
      let d = 5
      console.log(a)
      console.log(b)
    }
    console.log(b) 
    console.log(c)
    console.log(d)
}   
foo()
复制代码

上面代码在编译的过程中,var定义的变量会被放进变量环境中,let、const定义的变量会被放进词法环境中。执行时的查找顺序是先词法环境,后变量环境的查找。

总结:

  • 编译阶段会将变量、函数存储到变量环境中。
  • 执行阶段会对变量赋值,变量的查找和函数的查找。
文章分类
前端
文章标签