0%

2019-03-04-JS的执行阶段

JS 的执行阶段

当解释器解释完语法规则后,就开始执行,然后整个执行流程中大致包含:

  • 执行上下文,执行堆栈概念(如全局上下文,当前活动上下文)
  • VO(变量对象)和 AO(活动对象)
  • 作用域脸
  • this 机制

执行上下文

  • JS 有执行山下文
  • 浏览器首次载入脚本,它将创建「全局执行上下文」,并亚压入执行栈栈顶(不可以被弹出)
  • 然后每进入其他作用域就创建对应的执行上下文并把它压入执行栈的顶部
  • 一旦对应的上下文执行完毕,就会从栈顶端弹出,并将上下文控制权交给当前的栈
  • 依次进行,直至回到全局执行上下文

如果程序执行完成,被弹出执行栈,然后有没有被应用(没有形成闭包),那么这个函数中用的内存就被垃圾处理自动回收。

image

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

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

image

VO 和 AO

VO 是执行上下文的属性,但是只有全局上下文的变量对象允许通过 VO 的属性名称来间接访问(因为在全局上下文里,全局对象自身就是变量对象)

AO(activation object),当函数被调用者激活,AO 就被创建了。

1
2
在函数上下文中:VO === AO
在全局上下文中:VO === this === global

总体来说,VO 中会存放些变量信息(比如声明的变量,函数,arguments 参数等等)

作用域链

作为执行上下文的一个属性,原理和原型链很相似,作用很重要。

流程简述

1
2
3
4
在函数上下文中,查找一个变量foo
如果函数的VO中找到了,就直接使用
否则去它的父级作用域中(__parent__)找
以此往上级找寻,直到全局上下文中没有找到报错。

image

this 指针

this 是执行上下文环境的一个属性,而不是某个变量对象的属性

因此:

  • this 是没有一个类似搜寻变量的过程
  • 当代码中使用了 this,这个 this 的值就直接从执行上下文中获取了,而不会从作用域链中搜寻
  • this 的值在取决中进入上下文时的情况

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
var baz = 200;
var bar = {
baz: 100,
foo: function() {
consoloe.log(this.baz)
}
}

var foo = bar.foo;
// 进入环境: global
foo(); // 200,但是严格环境下会报错,Cannot ready property 'baz' of undefined
// 进入环境:global bar
bar.foo(); // 100