执行上下文

执行上下文:

函数在执行时,会创建一个执行上下文,用来记录函数在哪里执行,函数调用的方法,传入的参数等。执行上下文(execution context,简称:EC)也叫执行“执行环境”。 就是函数解析和执行所在环境的抽象概念。JavaScript 中运行任何的代码都是在执行上下文中运行。

类型:全局上下文、函数执行上下文、eval函数执行上下文

  • 全局上下文:是默认的、最基础的执行上下文。不在任何函数中的代码都位于全局执行上下文中。它做了两件事:
    1. 创建一个全局对象,在浏览器中这个全局对象就是 window 对象。
    1. 将 this指针指向这个全局对象。一个程序中只能存在一个全局执行上下文。
  • 函数执行上下文: 每次调用函数时,都会为该函数创建一个新的执行上下文。每个函数都拥有自己的执行上下文,但是只有在函数被调用的时候才会被创建。一个程序中可以存在任意数量的函数执行上下文
  • Eval 函数执行上下文: 运行在 eval 函数中的代码也获得了自己的执行上下文

eval(..) 可以在运行期修改书写期的词法作用域。
词法作用域是在函数在预编译阶段就确定了的,但是eval却在运行时,对词法作用域进行修改,消耗性能。

function foo(str, a) { 
    eval( str ); // 欺骗!
    console.log( a, b ); }
    var b = 2; 
    foo( "var b = 3;", 1 ); // 1, 3
}

类似eval的有,new Function(...),最后一个参数可以接受代码字符串,并将其转 化为动态生成的函数(前面的参数是这个新生成的函数的形参)。

with: 通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。

with 可以将一个没有或有多个属性的对象处理为一个完全隔离的词法作用域,因此这个对 象的属性也会被处理为定义在这个作用域中的词法标识符

function foo(obj) {
    with (obj) { a = 2; } 
}
var o1 = { a: 3 };
var o2 = { b: 3 };
foo( o1 ); 
console.log( o1.a ); // 2
foo( o2 ); 
console.log( o2.a ); // undefined 
console.log( a ); // 2——不好,a 被泄漏到全局作用域上了!
// o2 的作用域、foo(..) 的作用域和全局作用域中都没有找到标识符 a,因此当 a=2 执行 时,自动创建了一个全局变量(因为是非严格模式)。

执行上下文的生命周期

执行上下文的生命周期包括三个阶段:创建阶段→执行阶段→回收阶段

执行上下文包括:词法环境、变量环境

词法环境组件( LexicalEnvironment component) 和 变量环境组件( VariableEnvironment component)

ExecutionContext = {
  ThisBinding = <this value>,
  LexicalEnvironment = { ... },
  VariableEnvironment = { ... },
}

词法环境

词法环境是一种规范类型,基于 ECMAScript 代码的词法嵌套结构来定义标识符具体变量函数的关联。一个词法环境由环境记录器和一个可能的引用外部词法环境的空值组成。

简言之: 词法环境 是一种持有 标识符—变量映射 的结构。这里的 标识符 指的是变量/函数的名字,而 变量 是对实际对象(包含函数类型对象)或原始数据的引用

变量环境

变量环境 它也是一个 词法环境 ,所以它有着词法环境的所有特性。

在 ES5 的规范力要单独分出一个变量环境的概念是为 ES6 服务的: 在 ES6 中,词法环境组件和 变量环境 的一个不同就是前者被用来存储函数声明和变量(let 和 const)绑定,而后者只用来存储 var 变量绑定

ES5执行上下文

1. 程序启动,全局上下文被创建

  • 创建全局上下文的 词法环境
  1. 创建 对象环境记录器 ,它用来定义出现在 全局上下文 中的变量数的关系(负责处理 let 和 const 定义的变量)
  1. 创建 外部环境引用,值为 null
  • 创建全局上下文的 变量环境
  1. 创建 对象环境记录器,它持有 变量声明语句 在执行上下文中创建的绑定关系(负责处理 var 定义的变量,初始值为 undefined 造成声明提升
  1. 创建 外部环境引用,值为 null
  1. 确定 this 值为全局对象(以浏览器为例,就是 window )

2. 函数被调用,函数上下文被创建

  • 创建函数上下文的 词法环境

创建 声明式环境记录器 ,存储变量函数 和 参数,它包含了一个传递给函数的 arguments 对象(此对象存储索引和参数的映射)和传递给函数的参数的 length。(负责处理 let 和 const 定义的变量)

创建 外部环境引用,值为全局对象,或者为父级词法环境(作用域)

  • 创建函数上下文的 变量环境
  1. 创建声明式环境记录器 ,存储变量函数 和 参数,它包含了一个传递给函数的 arguments 对象(此对象存储索引和参数的映射)和传递给函数的参数的 length。(负责处理 var 定义的变量,初始值为 undefined 造成声明提升
  1. 创建 外部环境引用,值为全局对象,或者为父级词法环境(作用域)
  1. 确定 this 值

3. 进入函数执行上下文的执行阶段:

在上下文中运行/解释函数代码,并在代码逐行执行时分配变量值。

 

posted @ 2022-08-10 13:34  一叶一菩提22  阅读(106)  评论(0编辑  收藏  举报