上下文执行栈 执行栈

知识点:
 
 * 执行上下文
 * 每次函数执行的时候,会产生一个执行上下文,执行上下文是一个对象
 * 执行上下文里面会创建一个变量对象 ,里面存放着当前函数内的变量
 * 基本数据类型保存在变量对象里的,引用数据数据类型要单独在单堆内存里开辟空间保存。
 * 变量对象里保存的就是堆里的内存地址
 
 
1 function task(m, n) {
2     var a = 1;
3     var b = {
4         name: '张三'
5     }
6     var c = [1, 2, 3];
7 }
8 task(10, 20);

我们可以知道task的执行上下文

 1 let taskExecutionContext = {
 2     this: window,
 3     [[Scope]]: [函数的活动对象,全局的变量对象],
 4     //Variable Object 变量对象 里面存的是当前函数执行要使用到的变量
 5     VO: {
 6         m: 10,
 7         n: 20,
 8         a: 1,
 9         b: '内存地址指向对象{name: 张三}',
10         c: '内存地址指向数组[1,2,3]'
11     }
12 }

某个函数第一次被调用时,会创建一个执行环境(execution context)及相应的作用域链,并把作用域链赋值给一个特殊的内部属性(即 [[Scope]] )

当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activation object)作为变量对象。

执行环境(execution context,为简单起见,有时也称为“环境”)是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。

知识点:

 * 执行上下文栈
 * 栈是一个数据,里面放着很多执行上下文
 * 每次函数执行,都会产生一个执行上下文
 * 全局上下文的VO,也被称为GO (Global Object) 全局对象
 * 全局对象上的属性可以在任何地方被访问到
 * 在浏览端GO就是VO就是window
 
 
function one() {
    var a = 1;
    var two = () => {
        var b = 2;
        var three = () => {
            var c = 3;
            debugger
            console.log(a, b, c);
        }
        three();
    }
    two();
}
one();
 
执行上下文对象的VO栈
var executeContextStack = [];
//全局上下文 
var globalExecuteContext = {
    VO: { one: '()=>{}' }
}
// 全局执行环境是最外层的执行环境 executeContextStack
= [globalExecuteContext] var oneExecuteContext = { VO: { a: 1, two: '()=>{}' } }
// 执行到one把one推入环境栈中 executeContextStack
= [oneExecuteContext, globalExecuteContext] var twoExecuteContext = { VO: { b: 2, three: '()=>{}' } }
// 执行到two把two推入环境栈中 executeContextStack
= [, twoExecuteContext, oneExecuteContext, globalExecuteContext] var threeExecuteContext = { VO: { c: 3 } }
// 执行到three把three推入环境栈中 executeContextStack
= [threeExecuteContext, twoExecuteContext, oneExecuteContext, globalExecuteContext]
作用域链的查找过程
function getVariableValue(varName) {
    for (let i = 0; i < executeContextStack.length; i++) {
        if (varName in executeContextStack[i].VO) {
            return executeContextStack[i].VO[varName];
        }
    }
}
 
 * 当执行one的时候,会创建一个执行上下文 
 * 编译阶段
 *   创建VO 
 *      1. 处理参数,把参数放入VO
 *      2. 扫描所有代码,找出function声明,从上往下依次执行 在编译阶段,会处理所有的函数声明,如果有重复的声明
 * 后面会覆盖前面的声明
 *      3.扫描var关键字 var是不赋值,只声明,值是undefined 
 *      4.在编译阶段不会处理let变量的,let的变量也不会放在VO里
 *  编译完成
 *  开始执行阶段