执行上下文

  • 函数执行上下文:一个函数运行之前,创建的一块内存空间,空间中包含有该函数执行所需要的数据,为该函数执行提供支持。
  • 执行上下文栈:call stack,所有执行上下文组成的内存空间。
  • 栈:一种数据结构,先进后出,后进先出。
  • 全局执行上下文:所有JS代码执行之前,都必须有该环境。
  • JS引擎始终执行的是栈顶的上下文。

执行上下文中的内容

  1. this指向
    1). 直接调用函数,this指向全局对象
    2). 在函数外,this指向全局对象
    3). 通过对象调用或new一个函数,this指向调用的对象或新对象
  2. VO 变量对象
  • Variable Object:VO 中记录了该环境中所有声明的参数、变量和函数
  • Global Object: GO,全局执行上下文中的VO
  • Active Object:AO,当前正在执行的上下文中的VO
    1). 确定所有形参值以及特殊变量arguments
    2). 确定函数中通过var声明的变量,将它们的值设置为undefined,如果VO中已有该名称,则直接忽略。
    3). 确定函数中通过字面量声明的函数,将它们的值设置为指向函数对象,如果VO中已存在该名称,则覆盖。

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

  1. console.log(foo); //fn C
  2. var foo = "A";
  3. console.log(foo) //A
  4. var foo = function () {
  5. console.log("B");
  6. }
  7. console.log(foo); //fn B
  8. foo(); // B
  9. function foo(){
  10. console.log("C");
  11. }
  12. console.log(foo) //fn B
  13. foo(); // B

作用域链

  1. VO中包含一个额外的属性,该属性指向创建该VO的函数本身
  2. 每个函数在创建时,会有一个隐藏属性[[scope]],它指向创建该函数时的AO
  3. 当访问一个变量时,会先查找自身VO中是否存在,如果不存在,则依次查找[[scope]]属性。
  • 某些浏览器会优化作用域链,函数的[[scope]]中仅保留需要用到的数据。
  1. var foo = { n: 1 };
  2. (function (foo) {
  3. console.log(foo.n); // 1
  4. foo.n = 3;
  5. var foo = { n: 2 };
  6. console.log(foo.n); // 2
  7. })(foo);
  8. console.log(foo.n); // 3
  9. var food = "rice";
  10. var eat = function () {
  11. console.log(`eat ${food}`);
  12. };
  13. (function () {
  14. var food = "noodle";
  15. eat();//eat rice
  16. })();