Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

执行上下文 #3

Open
AngellinaZ opened this issue Feb 8, 2018 · 0 comments
Open

执行上下文 #3

AngellinaZ opened this issue Feb 8, 2018 · 0 comments

Comments

@AngellinaZ
Copy link
Owner

AngellinaZ commented Feb 8, 2018

参考: 冴羽的JavaScript深入系列, by冴羽; Neal_yang

执行上下文

当 JavaScript 代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。

执行上下文有三个重要的属性

  • 变量对象(Variable object,VO)
  • 作用域链(Scope chain)
  • this

变量对象(variable)

变量对象是一个数据作用域,存储了在执行上下文中定义的变量函数声明

全局上下文下的变量对象 : 全局对象
函数上下文下的变量对象 : 活动对象(activation object, AO)

AO是在进入函数上下文时刻被创建的,它通过函数的 arguments 属性初始化。arguments 属性值是 Arguments 对象。

进入上下文 (以下按照123的顺序执行)

  1. 函数的所有形参 (如果是函数上下文) -- arguments

    • 由名称和对应值组成的一个变量对象的属性被创建
    • 没有实参,属性值设为 undefined
  2. 函数声明

    • 由名称和对应值(函数对象(function-object))组成一个变量对象的属性被创建
    • 如果变量对象已经存在相同名称的属性,则完全替换这个属性
  3. 变量声明

    • 由名称和对应值(undefined)组成一个变量对象的属性被创建;
    • 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性(为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。)

代码执行

在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值

例子1:

function foo(a) {
  var b = 2;
  function c() {}
  var d = function() {};
  b = 3;
}
foo(1);
//进入上下文
AO = {
 arguments: {
     0: 1,
     length: 1
 },
 a: 1,
 b: undefined,
 c: reference to function c(){},
 d: undefined
}
//代码执行
AO = {
  arguments: {
      0: 1,
      length: 1
  },
  a: 1,
  b: 3,
  c: reference to function c(){},
  d: reference to FunctionExpression "d"
}

总结:

  1. 全局上下文的变量对象初始化是全局对象
  2. 函数上下文的变量对象初始化只包括 Arguments 对象
  3. 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值
  4. 在代码执行阶段,会再次修改变量对象的属性值

例子2:

console.log(foo); //3.打印

function foo(){  //1.函数声明
    console.log("foo");
}

var foo = 1;  //2.变量声明 3.赋值 foo = 1 
// 打印函数foo 
// 创建过程
VO = {
     foo: reference to function foo(){}
     // foo: undefined 
    // (如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。这个过程已被忽略)
}

// 执行过程 VO ->  AO
AO = {
    foo: reference to function foo(){}
}

例子3:

var foo = 1;
console.log(foo);  //1
function foo(){
  console.log("foo");
};
// 创建过程
VO = {
     foo: reference to function foo(){}
     // foo: undefined 
    // (如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。这个过程已被忽略)
}

// 执行过程 VO ->  AO
AO = {
    foo: 1 (此时函数已被重新赋值)
}

作用域链 scope chain

含义:由多个执行上下文的变量对象组成的链表

当代码在一个环境中执行的时候,会创建变量对象的一个作用域链

  • 作用域链的用途,是保证对执行环境有权访问的变量和函数的有序访问。
  • 作用域链的前端,始终是当前执行的代码所在的环境的变量对象。全局执行环境始终是作用域链的最后一个对象。
  • 内部环境可以通过作用域链访问外部环境的变量
var color = 'red';
function changeColor() {
  var anotherColor = 'blue';
  function swapColors() {
    var tempColor = anotherColor;
    anotherColor = color;
    color = tempColor;
    //这个执行环境中可以访问到 tempColor color antherColor
  }
  //这里只能访问anotherColor color
  swapColors();
}
changeColor();//这里只能访问color

action-scope

this 待读

this的指向,是在函数被调用的时候确定的。也就是执行上下文被创建时确定的

延长作用域链

try-catch 语句中的catch
width语句

垃圾收集

标记清除
主动清除垃圾: xxx = null

@AngellinaZ AngellinaZ changed the title 学习总结の执行上下文 执行上下文 Jun 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant