乐趣区

关于前端:拾遗记1VOvsAO

js 执行过程

当浏览器中的 GUI 线程解析 html 过程中发现 js 代码后,会告知 Browser 过程下载 js 文件。js 文件下载实现后,js 主引擎解析并执行 js。因为 js 主引擎和 GUI 线程互斥,所以在 js 执行过程中,GUI 线程挂起,html 解析暂停,直至 js 代码执行结束。

js 主引擎解析并执行 js 可分为三个步骤:

  1. 解释阶段(将取得的 js 字符串转换为计算机能够辨认的二进制)。
  2. 预编译阶段
  3. 执行阶段

因为 js 是脚本语言,因而预编译阶段和执行阶段是简直同时进行的,即编译一段代码就执行一段代码。

执行上下文

js 代码在执行之前会生成执行环境(EC),也能够称为执行上下文。

每当程序的执行流进入到一个可执行的代码时,就进入到了一个执行环境中。

执行上下文蕴含三种:

  1. 全局执行上下文。
  2. 函数执行上下文。
  3. eval 执行上下文。

执行上下文对象

生成执行环境时生成执行上下文对象,执行上下文对象如下

fn.ExecutionContext = { 
    variableObject: // 函数中的 arguments、参数、部分成员 
    scopeChains: // 以后函数所在的父级作用域中的流动对象 
    this: {} // 以后函数外部的 this 指向}

VO

在执行上下文对象中蕴含 variableObject 属性,也称为变量对象(VO)。此时,VO 中的变量只是申明,并没有赋值。

AO

当进入执行阶段后,执行上下文会局部发生变化,如下:

fn.ExecutionContext = {
    activationObject: // 函数中的 arguments、参数、部分成员
    scopeChains: // 以后函数所在的父级作用域中的流动对象
    this: {} // 以后函数外部的 this 指向}

此时,执行之前的变量对象(VO)变成了流动对象(AO),也就是实现了变量的赋值。

作用域链

作用域

作用域指明了一部分自在变量起作用的范畴,目前 js 蕴含三种,即:

  1. 全局作用域
  2. 函数作用域
  3. 块级作用域(ES2015 新增)

作用域链

函数在申明的时候会确定函数作用域,多个有关系的作用域合在一起能够造成作用域链。

function main() {
    // main 函数外部的作用域链保留着全局作用域
    return function inner() {// inner 外部的作用域链首先保留着 main 函数的作用域,还保留着全局作用域}
}

通过作用域链能够实现变量值的查找,如果 inner 函数执行的时候须要 a 变量,inner 函数首先查找本人的作用域,看是否定义了 a 变量,如果没有,则向上查找 main 函数的作用域,如果没有,则查找全局作用域,当整个查找链条都没有找到 a 变量,则会提醒 a 变量 undefined,反之,如果在某个作用域内受到变量 a,那么就进行查找。

作用域链要求只能从外向外查找,不能从外向内查找,也就是 main 函数查找变量时,只能查找自身作用域和全局作用域,而不能查找 inner 函数作用域。

应用闭包能够冲破变量作用域的限度,原来只能从一个作用域拜访内部作用域的成员,有了闭包之后,能够在内部作用域拜访一个外部作用域的成员。
退出移动版