执行上下文与作用域

1. 变量提升与函数提升

变量声明提升
  • 通过var定义(声明)的变量, 在定义语句之前就可以访问到
  • 值: undefined
函数声明提升
  • 通过function声明的函数, 在之前就可以直接调用
  • 值: 函数定义(对象)
  • 变量先提升,函数再提升

2. 执行上下文与执行上下文栈

执行上下文(EC):

由js引擎自动创建的对象, 包含对应作用域中的所有变量属性

它包含三个部分:
  • 变量对象(VO)
  • 作用域链(词法作用域)
  • this指向
它的类型:
  • 全局执行上下文
  • 函数执行上下文
  • eval执行上下文
生命周期
  • 全局 : 准备执行全局代码前产生, 当页面刷新/关闭页面时死亡
  • 函数 : 调用函数时产生, 函数执行完时死亡
包含哪些属性:
  • 全局 :
    • var定义的全局变量 ==>undefined
    • 使用function声明的函数 ===>function
    • this ===>window
  • 函数
    • var定义的局部变量 ==>undefined
    • 使用function声明的函数 ===>function
    • this ===> 调用函数的对象, 如果没有指定就是window
    • 形参变量 ===>对应实参值
    • arguments ===>实参列表的伪数组
执行上下文创建和初始化的过程

全局执行上下文

  • 在执行全局代码前将window确定为全局执行上下文
  • 对全局数据进行预处理
    *var定义的全局变量==>undefined, 添加为window的属性
    • function声明的全局函数==>赋值(fun), 添加为window的方法
    • this==>赋值(window)
  • 开始执行全局代码

函数执行上下文

  • 在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象
  • 对局部数据进行预处理
    • 形参变量==>赋值(实参)==>添加为执行上下文的属性
    • arguments==>赋值(实参列表), 添加为执行上下文的属性
    • var定义的局部变量==>undefined, 添加为执行上下文的属性
    • function声明的函数 ==>赋值(fun), 添加为执行上下文的方法
    • this==>赋值(调用函数的对象)
  • 开始执行函数体代码
执行上下文栈:

在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象

代码执行过程:
  • 创建 全局上下文 (global EC)
  • 全局执行上下文 (caller) 逐行 自上而下 执行。遇到函数时,函数执行上下文 (callee) 被push到执行栈顶层
  • 函数执行上下文被激活,成为 active EC, 开始执行函数中的代码,caller 被挂起
  • 函数执行完后,callee 被pop移除出执行栈,控制权交还全局上下文 (caller),继续执行

3. 作用域与作用域链

作用域:

一块代码区域(静态的), 在编码时就确定了, 不会再变化

作用域链:

多个嵌套的作用域形成的由内向外的结构, 用于查找变量

分类:
  • 全局
  • 函数
  • 块作用域(ES6 let)
变量的查找规则
  • 在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2
  • 在上一级作用域的执行上下文中查找对应的属性, 如果有直接返回, 否则进入3
  • 再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常
作用
  • 作用域: 隔离变量, 可以在不同作用域定义同名的变量不冲突
  • 作用域链: 查找变量
区别作用域与执行上下文
  • 作用域: 静态的, 编码时就确定了(不是在运行时), 一旦确定就不会变化了
  • 执行上下文: 动态的, 执行代码时动态创建, 当执行结束消失
  • 联系: 执行上下文环境是在对应的作用域中的

你可能感兴趣的:(执行上下文与作用域)