当浏览器中的GUI线程解析html过程当中发现js代码后,会告知Browser进程下载js文件。js文件下载完成后,js主引擎解析并执行js。因为js主引擎和GUI线程互斥,因此在js执行过程当中,GUI线程挂起,html解析暂停,直至js代码执行完毕。html
js主引擎解析并执行js可分为三个步骤:浏览器
因为js是脚本语言,所以预编译阶段和执行阶段是几乎同时进行的,即编译一段代码就执行一段代码。闭包
js代码在执行以前会生成执行环境(EC),也能够称为执行上下文。函数
每当程序的执行流进入到一个可执行的代码时,就进入到了一个执行环境中。
执行上下文包含三种:this
生成执行环境时生成执行上下文对象,执行上下文对象以下线程
fn.ExecutionContext = { variableObject: // 函数中的 arguments、参数、局部成员 scopeChains: // 当前函数所在的父级做用域中的活动对象 this: {} // 当前函数内部的 this 指向 }
在执行上下文对象中包含variableObject属性,也称为变量对象(VO)。此时,VO中的变量只是声明,并无赋值。code
当进入执行阶段后,执行上下文会部分发生变化,以下:htm
fn.ExecutionContext = { activationObject: // 函数中的 arguments、参数、局部成员 scopeChains: // 当前函数所在的父级做用域中的活动对象 this: {} // 当前函数内部的 this 指向 }
此时,执行以前的变量对象(VO)变成了活动对象(AO),也就是完成了变量的赋值。对象
做用域指明了一部分自由变量起做用的范围,目前js包含三种,即:进程
函数在声明的时候会肯定函数做用域,多个有关系的做用域合在一块儿能够造成做用域链。
function main() { // main函数内部的做用域链保存着全局做用域 return function inner() { // inner内部的做用域链首先保存着main函数的做用域,还保存着全局做用域 } }
经过做用域链能够完成变量值的查找,若是inner函数执行的时候须要a变量,inner函数首先查找本身的做用域,看是否认义了a变量,若是没有,则向上查找main函数的做用域,若是没有,则查找全局做用域,当整个查找链条都没有找到a变量,则会提示a变量undefined,反之,若是在某个做用域内遭到变量a,那么就中止查找。
做用域链要求只能从内向外查找,不能从外向内查找,也就是main函数查找变量时,只能查找自己做用域和全局做用域,而不能查找inner函数做用域。
使用闭包能够突破变量做用域的限制,原来只能从一个做用域访问外部做用域的成员,有了闭包以后,能够在外部做用域访问一个内部做用域的成员。