js解析顺序以中深度分析闭包
一、JS代码执行过程
我们都知道,JS语言是一种单线程解释性语言。它是一门语言,它有它自己的执行机制。来看下吧。
JS代码执行过程分三个过程:
-
语法分析,语法分析就是浏览器先通栏浏览一下整体的代码有没有少写分号、单词拼错等语法的错误。
-
JS预编译,本质是创建
AO对象
和GO对象
,对其属性的操作。 -
解释性执行.就是一行一行的读取代码执行代码。
下面我们着重讲一下JS预编译
二、JS预编译(作用域)
GO对象(全局作用域):当全局代码执行的前期会创建一个执行期的上下文对象
- 创建GO对象 GO{}
- 找变量声明,将变量名最为GO对象的属性名,值为undefined
- 找函数声明,值赋予函数体
AO对象(局部作用域):当代码执行的前期,会创建一个执行期上下文的内部对象 (作用域)
- 创建AO对象 AO{}
- 找形参和变量声明,将变量和形参名,当做AO对象的属性名,值为undefined
- 实参形参相统一
- 在函数体里面找函数声明,值赋予函数体
PS:
- AO对象和GO对象都是预编译的时候创建出来的,因为当函数被调用的时候,会先进行预编译
- 要注意上面是函数声明,要区分函数声明和函数表达式。在预编译阶段函数表达式不进行声明。
console.log(a);
console.log(b);
var a = 1,
b = 2;
if (false) {
var c = 3;
}
function a() {
console.log("函数a");
}
var b = function() {
console.log("函数b");
}
console.log(a);
console.log(b);
console.log(c);
三、闭包
3.1、闭包以及其形成的条件
1、什么是闭包?
闭包简单的来说就是:函数套函数
闭包可以引用到外部函数的变量和参数,但外部函数不可以引用闭包的变量和参数。
2、形成闭包的条件?
- 函数的嵌套
- 内部函数引用外部函数的变量
- 内部的函数是在父级作用域之外进行引用(重点)
3.2、闭包不会被垃圾回收机制回收的原因
作用域链:会被保存到一个隐式的属性中去[[scope]]
,这个属性是我们用户访问不到的。但确实存在的,由js引擎来访问的。[[scope]]
是AO对象
和GO对象
的集合。
如下代码的作用域链:
function a() {
var i = 0;
return function b() {
console.log(i++);
}
}
var res = a();
res();
res();