概述
javascript是单线程的解释性语言,单线程就是先执行完一个,再执行另一个,解释性语言就是先翻译一行,再执行一行,先翻译一行,再执行一行,但是js在执行之前通常会先通篇扫描一遍代码,而不执行代码,通篇扫描就是看看代码有没有什么低级语法错误,这个过程(通篇扫描)就叫语法(义)分析,而在通篇扫描完成之后,才真正开始预编译过程,最后才开始解释一行,执行一行,解释一行,执行一行
js运行3部曲 语法分析、 预编译、解释执行
function fn (a){
console.log(a);
var a =111;
console.log(a);
function a(){}
console.log(a);
var b =function(){}
console.log(b);
function d(){}
}
fn(1)
预编译
预编译就是把函数参数,变量声明,函数声明提升到逻辑的最前面,发生在函数执行的前一刻
- 第一步
创建执行上下文
每当函数执行时,会创建一个称为执行上下文的内部对象(可理解为作用域)。一个执行上下文定义了一个函数执行时的环境。(执行一次,创建一次)
(1)创建作用域链(Scope Chain)。
(2)创建变量对象(函数的形参、函数声明、变量声明)。
(3)求”this“的值。
例子: 创建AO(执行上下文)
AO{
}
- 第二步
找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
AO{
a :undefined
b :undefined
}
- 第三步
将形参值和实参相统一,将实参的值赋予形参(a的undefind值被覆盖为1)
AO{
a :1
b :undefined
}
- 第四步
- 在函数体里面找函数声明,值赋予函数体
AO{
a :function a(){}
b :undefined
d:function d(){}
}
执行阶段
AO对象创建完后,开始执行上面函数
function fn (a){
console.log(a); // :function a(){}
var a =123;
console.log(a); //123
function a(){}
console.log(a); //123
var b =function(){}
console.log(b); //:function (){}
function d(){}
}
fn(1)
解释
函数声明是整体 提升
变量声明提升(变量声明就是 var a =10,其中的 var a;就是变量声明,var a=10;表示变量声明+变量附值 )变量声明提升就相当于把var a=10;拆分成var a ; 跟a =10,然后把var a;提升到逻辑的最前面
作用域链:作用域链是一个当前函数所在的可变对象的列表,其中包括GEC()的可变对象和当前函数的可变对象。
总结
1.代码分类(位置):
- 全局代码
- 函数代码
2.全局执行上下文
(1) 在执行全局代码前将window确定为全局执行上下文
(2)对全局数据进行预处理
- var定义的全局变量===>undefined,添加为window的属性
- function声明的全局函数===>赋值(fun),添加为window的方法
- this===>赋值(window)
(3) 开始执行全局代码
3.函数执行上下文
(1) 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
(2) 对局部数据进行预处理
- 形参变量==>赋值(实参),添加为执行上下文的属性
- arguments==>赋值(实参列表),添加为执行上下文的属性
- var定义的局部变量==>undefined,添加为执行上下文的属性
- function声明的函数==>赋值(fun),添加为执行上下文的属性
- this==>赋值(调用函数的对象)
(3) 开始执行函数体代码