执行上下文概念
执行上下文就是评估和执行javascript代码的环境的抽象概念.每当javascript运行的时候,它都是在执行上下文中运行
执行上下文的类型
- 全局执行上下文: 这是默认的上下文,任何不在函数外部的代码都在全局上下文中.它会执行两件事: 创立一个全局window,并且设置this的值指向这个window. 一个程序中只有一个全局执行上下文
- 函数执行上下文: 每当一个函数被调用时, 都会为该函数创立一个新的上下文. 每个函数都有它本人的执行上下文, 不过都是在函数被调用时创立的. 函数上下文能够有多个, 每当一个新的执行上下文创立时, 它会依照定义的程序执行一系列的步骤.
执行栈
是一种领有后进先出数据结构的栈, 被用来贮存代码运行时创立的所有执行上下文
为了模仿执行上下文栈的行为,让咱们定义执行上下文栈是一个数组:
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();
思考题:
// 比拟上面两段代码,试述两段代码的不同之处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
然而执行上下文栈的变动不一样
第一段代码
ECStack.push(<checkscope> functionContext)ECStack.push(<f> functionContext)ECStack.pop()ECStack.pop()
模仿第二段代码
ECStack.push(<checkscope> functionContext)ECStack.pop()ECStack.push(<f> functionContext)ECStack.pop()
作用域
作用域是程序源代码中定义变量的区域
作用域规定了如果查找变量,也就是确定以后执行代码对变量的拜访权限.
词法作用域: javascript采纳的是词法作用域 也就是动态作用域, 函数的作用域是在定义的时候就决定了
动静作用域: 函数的作用域是在函数调用的时候才决定的
看上面例子
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