2019-06-18

作者: 青色琉璃 | 来源:发表于2019-06-18 09:39 被阅读0次

    执行上下文(Execution Context):函数执行前进行的准备工作(也称执行上下文环境)。

      当执行代码进入一个环境时,就会为该环境创建一个执行上下文,它会做一些准备工作,如变量提升,确定作用域等。


    一,执行上下文的类型

      js中有三种执行上下文类型:

    全局执行上下文:顶层上下文,任何不在函数内部的代码都在其中。上下文中的大哥大!它干了两件事:1.创建一个全局的window对象(浏览器环境下),2.设置this的值等于这个全局对象。(一个程序中只会有一个全局执行上下文)

    函数执行上下文:函数被调用时,会创建新的上下文,可以有多个。

    Eval函数执行上下文:aval函数专用,用的不多,没排面,不讨论。

    执行栈

    在js中,通过栈的存取方式来管理执行上下文,我们可称其为执行栈,或函数调用栈(Call Stack)。

    栈遵循“先进先出,后进后出”的规则,也就是LIFO(Last In First Out)规则,可以用乒乓球盒子来类比理解。

    特点:

    1,先进先出,后进后出

    2,出口在顶部,且仅有一个

      当js引擎第一次遇到你的脚本时,它会创建一个全局的执行上下文并且压入当前执行栈。而每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。

      引擎会执行那些位于执行上下文顶栈顶的函数,当函数执行结束时,其执行上下文从栈中弹出,控制流程达到当前栈中的下一个上下文。

      我们可以通过示例代码来理解:

    function foo () {

       function bar () {

           return 'I am bar';

       }

       return bar();

    }

    foo();

    二,执行上下文的生命周期

    执行上下文的生命周期有两个阶段:

    创建阶段(进入执行上下文,如:变量提升等)

    执行阶段

    创建阶段的操作:

    1,创建变量对象

    函数环境会初始化创建Arguments对象(并赋值),并传递长度length

    匿名函数声明(并赋值)

    变量声明,函数表达式声明(未赋值,即变量提升)

    2,确定this指向(this由调用者确定)

    3,确定作用域(词法环境确定,哪里声明,哪里确定)

    执行阶段的操作

    1,变量对象赋值

    变量赋值

    函数表达式赋值

    2,调用函数

    3,执行其他代码片段

    值得注意的是,执行上下文可存在多个,因此在递归中可能因为没有终止条件而造成死循环,堆栈溢出错误。

    // 递归调用自身

    function foo() {

     foo();

    }

    foo();

    // 报错: Uncaught RangeError: Maximum call stack size exceeded


    文末总结:

    1,js是单线程

    2,栈顶的执行上下文处于执行中时,其他的需要排队

    3,处于底部的总是全局上下文,关闭页面时出栈

    4,函数执行上下文可存在多个,但应避免递归时堆栈溢出

    5,函数调用时就会创建新的上下文,即使调用自身,同样如此

    参考文档:

    https://mp.weixin.qq.com/s/lAvyjfBZvX0E50QiW3aW7w

    https://juejin.im/post/5ba32171f265da0ab719a6d7(并未讨论其中的词法环境)

    相关文章

      网友评论

        本文标题:2019-06-18

        本文链接:https://www.haomeiwen.com/subject/ucdxqctx.html