执行上下文 也就是预编译

函数执行上下文:一个函数运行之前,创建的一块内存空间,空间中包含有该函数执行所需要的数据,为该函数执行提供支持。

执行上下文栈:call stack,所有执行上下文组成的内存空间。

栈:一种数据结构,先进后出,后进先出。

全局执行上下文:所有JS代码执行之前,都必须有该环境。其中第一个执行环境是全局执行环境

JS引擎始终执行的是栈顶的上下文。

this指向

全局this指向window
直接调用函数,this指向全局对象
在函数外,this指向全局对象
通过对象调用或new一个函数,this指向调用的对象或新对象

VO 变量对象

Variable Object:VO 中记录了该环境中所有声明的参数、变量和函数

Global Object: GO,全局执行上下文中的VO

Active Object:AO,当前正在执行的上下文中的VO
首先会创建一个全局的环境也就是GO
1:查找通过var声明的变量,并将它设置为unfinished,如果已有该名称,则直接忽略
2:查找通过自变量声明的函数.并将他们的值设置为指向函数对象 ,如果已存在该名称则会覆盖,
其次是 VO 与 AO
1:确定所有形参值以及特殊变量arguments
2:查找通过var声明的变量,并将它设置为unfinished,如果已有该名称,则直接忽略
3:查找通过自变量声明的函数.并将他们的值设置为指向函数对象 ,如果已存在该名称则会覆盖,

当一个上下文中的代码执行的时候,如果上下文中不存在某个属性,则会从之前的上下文寻找。

作用域链

  1. VO中包含一个额外的属性,该属性指向创建该VO的函数本身
  2. 每个函数在创建时,会有一个隐藏属性[[scope]],它指向创建该函数时的AO
  3. 当访问一个变量时,会先查找自身VO中是否存在,如果不存在,则依次查找[[scope]]属性

某些浏览器会优化作用域链,函数的[[scope]]中仅保留需要用到的数据。

  1. var g = 0;
  2. function A() {
  3. var a = 1;
  4. function B() {
  5. var b = 2;
  6. var C = function() {
  7. var c = 3;
  8. console.log(c, b, a, g);
  9. }
  10. C();
  11. }
  12. B();
  13. }
  14. A();

上面代码的作用域链以及执行上下文 如下
image.png