JavaScript引擎在代码执行前会进行以下操作:首先进行分词/词法分析将语句分成token,之后整个作用域分析完成后,JS引擎会解析/语法分析token并翻译成AST(AbstractSyntaxTree)预编译(preprocessing),同时解释执行(不是纯解释,也有JIT编译,这里不展开)Precompilation(预处理))有人说JavaScript没有预编译,预编译是语法分析的一部分。编译在执行前需要几毫秒。因此,对于JavaScript是否预编译,或者这些步骤是否属于预编译(预处理),众说纷纭,暂不讨论。“预编译”放。全局预编译创建一个GlobalObject全局上下文对象找到一个变量声明,将变量名绑定为GO的一个属性,值为undefined找到一个函数声明,将函数名绑定为GO的一个属性,值为函数body本地执行全局代码预编译创建ActivationObject函数上下文对象找到line参数,将line参数名绑定为AO的一个属性,值为undefined,找到一个变量声明,将变量名绑定为AO的一个属性,并将实参值undefined赋值给形参找到函数声明,将函数名绑定为AO的一个属性,为函数体函数生成一个[[scope]]属性作为值,并且value是一个数组,数组的第一项是这个函数的AO,下一项是外层函数的AO,一直走到外层,直到最后一项是GOexe切割功能代码声明提升。作用域链之上的预编译的前半部分是所谓的声明提升。声明提升我有一篇单独讲,就不细说了。单击此处了解详情。`[[scope]]`属性会在函数执行前生成,值为数组。数组的第一项是这个函数的AO,下一项是外层函数的AO,一直到外层,直到最后一项是GOAO。函数的作用域,像[[scope]]这样的链接数组就是函数的作用域链。当函数进行值查询RHS时,会先搜索[[scope]]中的第一项,如果没有找到再搜索第二层,以此类推,直到找到GO。关闭当函数FN的执行结束时,这个函数FN的AO的生命周期应该结束,需要销毁。但是有一个特例,虽然是特例,但是在开发中很常见,就是函数FN执行后返回一个内部函数A并保存在外部,函数FN的AO应该havebeendestroyed不能被销毁,因为函数A的[[scope]]保存了函数FN的AO作为其原型链的一部分。只要函数A的变量不被销毁或者变量所在的AO不被销毁,函数FN的AO就永远不会被销毁,而变量保存的函数A始终可以访问变量和值在函数FN中。这种现象称为闭包。大量这样的闭包会导致内存泄漏或加载缓慢。如何产生闭包:当内部函数返回到外部并保存时,产生闭包。什么是闭包:闭包是一个可以读取其他函数内部变量的函数。varVariable_1=1;functionFN(){varVariable_2=2;函数A(){varVariable_3=3console.log(Variable_2);}返回A;}varFunction_A=FN();FnVariable();//接受函数A的变量Function_A可以通过调用输出FN中的Variable_2
