当Javascript执行一段可执行代码时,会创建对应的执行上下文
    对于每个执行上下文,都有三个重要属性:
    1、变量对象
    2、作用域链
    3、this
    之前三篇文章对于这三部分都有讲解。我们用一段代码来进行分析

    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() // local scope

    执行过程如下:
    1、执行全局代码,创建全局上下文,全局上下文被压入全局上下文栈

    1. ECStack = [
    2. globalContext
    3. ]

    2、全局上下文初始化

    1. golbalContext = {
    2. VO: [global],
    3. Scope: [globalContext.VO],
    4. this: globalContext.VO
    5. }

    2、初始化的同时,checkscope函数被创建,保存作用域链到函数的内部属性[[scope]]

    1. checkscope.[[scope]] = {
    2. globalContext.VO
    3. }

    3、执行checkscope函数,创建checkscope函数执行上下文,checkscope函数执行上下文被压入执行上下文栈中

    1. ECStack = [
    2. checkscopeContext,
    3. globalContext
    4. ]

    4、checkscope函数执行上下文初始化:
    一、赋值函数[[scope]]属性创建作用域
    二、用arguments创建活动对象
    三、初始化活动对象,即加入形参、函数声明、变量声明
    四、将活动对象压入checkscope作用域链顶端
    同时f函数被创建,保存作用域链到f函数的内部属性[[scope]]

    1. checkscopeContext = {
    2. AO: {
    3. arguments: {
    4. length: 0
    5. },
    6. scope: undefined,
    7. f: reference to function f() {}
    8. },
    9. Scope: [AO, globalContext.VO],
    10. this: undefined
    11. }

    5、执行f函数,创建f函数执行上下文,f函数执行上下文被压入执行上下文栈

    1. ECStack = [
    2. fContext,
    3. checkContext,
    4. globalContext
    5. ]

    6、f函数执行上下文初始化 ,以下跟第四步相同:
    一、复制函数[[scope]]属性创建作用域链
    二、用arguments创建变量对象
    三、初始化活动对象,即加入形参、函数声明、变量声明
    四、将活动对象压入f作用域链顶端

    1. fContext = {
    2. AO: {
    3. arguments: {
    4. length: 0
    5. }
    6. },
    7. Scope: [AO, checkscopeContext.AO, globalContext.VO],
    8. this: undefined
    9. }

    7、函数执行,沿着作用域链查找scope值,返回scope值
    8、f函数执行完毕,checkscope执行上下文从执行上下文栈中弹出

    1. ECStack = [
    2. globalContext
    3. ]

    :::info 本文档引用自冴羽大神的博客:传送门 :::