执行上下文

1.什么是“执行上下文”

通俗的定义就是:在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。
执行上下文可以简单理解为一个对象:
它包含三个部分:

  • 变量对象(VO)
  • 作用域链(词法作用域)
  • this指向

类型:

  • 全局执行上下文
  • 函数执行上下文
  • eval执行上下文

代码执行过程:

  • 创建 全局上下文 (global EC)
  • 全局执行上下文 (caller) 逐行 自上而下 执行。遇到函数时,函数执行上下文 (callee) 被push到执行栈顶层
  • 函数执行上下文被激活,成为 active EC, 开始执行函数中的代码,caller 被挂起
  • 函数执行完后,callee 被pop移除出执行栈,控制权交还全局上下文 (caller),继续执行

    2.示例

    先来看几段代码

    1. console.log(a)

    image.png

    1. console.log(a)
    2. var a

    image.png

    1. console.log(a)
    2. var a = 1

    image.png
    第三断代码输出的是undefined,说明浏览器在执行console.log(a)时,已经知道了a是undefined,但是却不知道它是10。

    3.变量提升

    我们要了解一下什么是变量提升
    先来看一段代码

    1. console.log(a) //undefined
    2. var a = 100
    3. fn('zhangsan') //'zhangsan' 20
    4. function fn(name){
    5. age = 20
    6. console.log(name,age)
    7. var age;
    8. }

    当我们看到这段代码的执行结果时是否会产生一个疑惑?为何函数先执行,后定义时一样可以正确的调用函数。
    在解析代码之前我们先了解一下变量提升的概念。

    变量提升

    在使用javascript编写代码的时候, 我们知道, 声明一个变量用var, 定义一个函数用function.那你知道程序在运行它的时候, 都经历了什么吗?

    变量声明提升

    首先是用var定义一个变量的时候, 例如:

    1. var a = 10;

    大部分的编程语言都是先声明变量再使用, 但是javascript有所不同, 上面的代码, 实际相当于这样执行:

    1. var a;
    2. a = 10;

    因此有了下面这段代码的执行结果:

    1. console.log(a); // 声明,先给一个默认值undefined;
    2. var a = 10; // 赋值,对变量a赋值了10
    3. console.log(a); // 10

    这就是最简单的变量声明提升.
    典型题 ```javascript function foo() {

    console.log(‘foo1’);

}

foo(); // foo2

function foo() {

  1. console.log('foo2');

}

foo(); // foo2

  1. 打印的结果是两个 `foo2`
  2. ```javascript
  3. var scope = "global scope";
  4. function checkscope(){
  5. var scope = "local scope";
  6. function f(){
  7. return scope;
  8. }
  9. return f();
  10. }
  11. checkscope();
  1. var scope = "global scope";
  2. function checkscope(){
  3. var scope = "local scope";
  4. function f(){
  5. return scope;
  6. }
  7. return f;
  8. }
  9. checkscope()();

两段代码执行的结果一样

小结

  • JavaScript 代码执行过程中,需要先做变量提升,而之所以需要实现变量提升,是因为 JavaScript 代码在执行之前需要先编译
  • 编译阶段,变量和函数会被存放到变量环境中,变量的默认值会被设置为 undefined;在代码执行阶段,JavaScript 引擎会从变量环境中去查找自定义的变量和函数。
  • 如果在编译阶段,存在两个相同的函数,那么最终存放在变量环境中的是最后定义的那个,这是因为后定义的会覆盖掉之前定义的。