概念
执行环境(Execution context,简称EC)或执行上下文对象(后面统一用执行上下文表示),它定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。是不是有点不好理解,先简单翻译下: js代码执行时所在的环境。继续后面
在JavaScript中执行环境分三种:
- 全局执行环境 : 这个是最外围的执行环境,一旦代码被载入,引擎最先进入的就是这个环境。在浏览器中,全局环境就是window对象,因此所有全局属性和函数都是作为window对象的属性和方法创建。全局执行环境直到应用程序退出时才会被销毁。
- 函数执行环境:当执行流执行一个函数时,javascript会创建一个新的函数执行环境,函数执行环境中的代码执行完之后,该环境销毁,保存在其中的所有变量和函数定义也被之销毁。
- Eval(一个普通函数,但是他有一个快速通道通向编译器,可以将string变成可执行的代码)执行环境 : Eval的执行环境和函数调用的执行环境相同。
执行环境组成
当JavaScript代码执行一段可执行代码时,会创建对应的执行上下文(execution context)。对于每个执行上下文,都有三个重要属性:
- 变量对象(Variable object,VO)
- 作用域链(Scope chain)
- this
执行过程
- 创建上下文对象(可以理解为初始化某些属性)
- 代码执行(赋值、改变值等操作)
后续分别在《执行环境之变量对象》、《执行环境之作用域链》、《执行环境之this指针》介绍这三个属性,这里只是简单介绍执行环境,后续会具体介绍执行环境。
执行上下文栈
那么现在问题来了,平时工作中写的全局变量,函数以及嵌套函数应该不少了吧,每执行一个函数就会创建一个新的函数执行上下文,想想那么多执行上下文是不是有点恐怖,那么js又是如何管理那么多的执行上下文呢?
当执行流执行一个函数时,就会给当前函数创建执行上下文,并且将该执行上下文被推入一个执行上下文栈中(Execution context stack,ECS),在函数执行完之后,执行上下文栈将被弹出,并且把控制器返回给之前执行的执行上下文;
注意,一个函数可能会创建无数的上下文,因为对函数的每次调用(即使这个函数递归的调用自己)都会生成一个具有新状态的上下文;
根据工作原理执行上下文栈类似一个数组结构 ,我们模拟执行上下文栈的行为:
1 ECStack = []; //先定义执行上下文栈是一个数组:
JavaScript 开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文,用 globalEC表示它,并且只有当整个应用程序结束的时候,ECStack 才会被清空,所以 ECStack 最底部永远有个 globalEC:
1 ECStack = [ 2 globalEC 3 ];
现在 JavaScript 遇到下面的这段代码了:
1 <script> 2 function run3() { 3 console.log('run3') 4 } 5 6 function run2() { 7 run3(); 8 } 9 10 function run1() { 11 run2(); 12 } 13 run1(); 14 </script>
当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。知道了这样的工作原理,让我们来看看如何处理上面这段代码:
1 // 伪代码 2 3 // run1() 推入执行上下文栈 4 ECStack.push(run1.EC); 5 6 // run1中调用了run2,创建run2的执行上下文 推入执行上下文栈 7 ECStack.push(run2.EC); 8 9 // run2还调用了run3,创建run3的执行上下文 推入执行上下文栈 10 ECStack.push(run3.EC); 11 12 // run3执行完毕 13 ECStack.pop(); 14 15 // run2执行完毕 16 ECStack.pop(); 17 18 // run1执行完毕 19 ECStack.pop(); 20 21 // javascript接着执行下面的代码,但是ECStack底层永远有个globalContext,直到应用程序退出(例如关闭网页)
回顾定义
执行环境(Execution context,简称EC)或执行上下文对象,它定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。
当执行流进入一个函数时,创建执行上下文对象,然后推入执行上下文栈。是不是感觉跟定义相差太远,难道是《javascript高程程序设计》写错了?
当然不是,执行上下文到底包含了哪些内容所以欢迎阅读下一篇《javascript 之变量对象》。