执行上下文就是评估和执行javascript代码的环境的抽象概念.每当javascript运行的时候,它都是在执行上下文中运行javascript
是一种拥有后进先出数据结构的栈, 被用来储存代码运行时建立的全部执行上下文
为了模拟执行上下文栈的行为,让咱们定义执行上下文栈是一个数组:java
ECStack = [];
当javascript引擎第一次遇到你的脚本时.它会建立一个全局的执行上下文,而且压入当前执行栈,也就是数组ECStack中.数组
ECStack = [ globalContext ];
每当引擎遇到一个函数调用.它会为该函数建立一个新的执行上下文而且压入当前执行栈的顶部.数据结构
引擎会执行那些执行上下文位于栈顶的函数。当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文
如今javascript遇到下面的这段代码:函数
function fun3() { console.log('fun3') } function fun2() { fun3(); } function fun1() { fun2(); } fun1();
// fun1() ECStack.push(<fun1> functionContext); // fun1中调用了fun2,还要建立fun2的上下文 ECStack.push(<fun2> functionContext); // fun2调用了fun3 ECStack.push(<fun3> functionContext); // fun3 执行完毕 ECStack.pop(); // fun2 执行完毕 ECStack.pop(); // fun1 执行完毕 ECStack.pop();
思考题:this
// 比较下面两段代码,试述两段代码的不一样之处 var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope(); // // B--------------------------- var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f; } checkscope()();
上面两端代码输出值是同样的, 都是local scope
可是执行上下文栈的变化不同
第一段代码code
ECStack.push(<checkscope> functionContext) ECStack.push(<f> functionContext) ECStack.pop() ECStack.pop()
模拟第二段代码ip
ECStack.push(<checkscope> functionContext) ECStack.pop() ECStack.push(<f> functionContext) ECStack.pop()
做用域是程序源代码中定义变量的区域
做用域规定了若是查找变量,也就是肯定当前执行代码对变量的访问权限.
词法做用域: javascript采用的是词法做用域 也就是静态做用域, 函数的做用域是在定义的时候就决定了
动态做用域: 函数的做用域是在函数调用的时候才决定的作用域
看下面例子io
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar();
假如javascript采用静态做用域.
执行foo函数,先从foo函数内部查找是否有局部变量value.若是没有,就根据书写的位置,查找上面一层代码. 也就是value等于1. 因此结果会打印1
假设javascript采用动态做用域.执行foo函数.依然是从foo函数内部查找是否有局部变量value.若是没有.就从调用函数的做用域. 也就是bar函数内部查找value变量,因此打印2