1. 执行上下文
1.1 执行上下文
- 可以理解为当前代码的运行环境,作用是用来保存当前代码运行时所需要的数据。在全局环境、函数环境中会创建执行上下文
- 函数执行时才会创建执行上下文。当一个函数调用时,一个新的执行上下文就会被创建
- 每个执行上下文都有一个与之关联的变量对象和一个作用域
- 执行上下文的生命周期包括创建阶段、执行阶段以及等待回收阶段
1.2 执行上下文栈
执行上下文栈按照函数的调用顺序来管理执行上下文,栈底永远是全局上下文,栈顶是当前正在执行的函数
遇到return语句销毁当前执行上下文,弹出执行上下文栈
2. 变量对象
变量对象是与执行上下文相关的数据作用域,用于存储被定义在上下文中的变量和函数声明
3. 作用域链
3.1 作用域
作用域是一套关于如何存储变量当中的值,并且能在之后对这个值进行访问和修改的规则。它指定了变量与函数的可访问范围并控制其可见性
3.1.1作用域类型
- 全局作用域:全局作用域中无法访问到局部作用域中的变量。全局变量包括全局作用域下var声明的变量,函数内部,没有使用var关键字声明直接赋值的变量以及window全局对象创建的属性和方法
- 函数作用域: 局部作用域可以访问到全局作用域中的变量。局部变量包括函数内部var声明的变量以及函数的形参
- 块作用域(ES5中没有块作用域,ES6中添加了块作用域):任何一对花括号 { } 中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域
3.1.2 作用域模型
JavaScript采用词法作用域
-
词法作用域(静态性):JavaScript 的作用域在代码的编译阶段就已确定。但是通过 new Function 创建的函数对象不遵从静态词法作用域,其总是在全局作用域中执行
-
动态作用域(动态性)
var x = 10;
function foo(){
console.log(x);
}
foo();
function fun(){
var x = 20;
var foo1 = foo;
foo1();
}
fun();
// 当 fun 函数被调用时:
// fun 函数被调用,创建了 fun 的执行上下文。
// 在 fun 函数内部,局部变量 x 被赋值为 20。
// foo 函数被赋值给变量 foo1。
// foo1 被调用,实际上是调用了 foo 函数。
// foo 函数在执行时,会打印它所在作用域链中的变量 x 的值。
//由于 foo 函数在全局作用域中定义,并且没有在 foo 函数内部重新定义变量 x,所以它将打印全局变量 x 的值,即 10。
3.2 作用域链
由当前执行环境与所有父级执行环境的一系列变量对象组成,提供对变量和函数访问的权限和顺序的规则
变量函数会沿着作用域链从里向外查找,在找到第一个匹配的标识符时停止