js的预编译的过程就是声明提前的过程,其中有两个提升。
1.变量声明提升
2. 函数声明整体提升(优先级最高)
我们先说一下函数里面的声明提升的四大解读规则:
1.创建函数的AO对象(也就是执行上下文)
2.找出形参和实参,,将形参和实参作为AO对象的属性,值为undefined
3.将实参和形参的值统一
4.在函数体内找出函数声明,函数名作为AO对象的属性,值为函数体
eg:
a=100
function demo(e){
function e(){}
arguments[0]=2
console.log(e)
if(a){
var b=123
function c(){}
}
var c
a=10
var a
console.log(b)
f=123
console.log(c)
console.log(a)
}
var a
demo(1)
console.log(a)
console.log(f)
首先代码运行的时候创建了一个全局对象global也就是我们常说的window,然后将全局里面的所有的声明变量和全局的函数声明提前
{
a:undefined,
demo:function(){}
}
然后程序开始运行,执行到demo(1)时,又创建了demo的执行上下文AO对象,然后将所有的声明变量和函数声明提前,作为属性名放到AO对象里面,值为undefined
{
e: function(){} // 一开始是形参e,值为undefined,随后变成实参e,值为1,最后函数声明提前,变成值function(){}的函数体
b:undefined, //由于js不具备函数块级作用域的概念,所以b也需要声明提前
c:undfined, // 由于最新的chrome浏览器不在支持if里面进行函数声明,所以c的值为最外面的var c的值undefined
a:undefined // 是var a声明的一个变量,值为undefined
}
由于arguments[0]指代的就是实参e,所以当arguments[0]进行赋值的时候e的值也跟着改变了,所以e为2,不再是函数体
由于变量声明提前的原因,a的变量的值为undefined,所以if语句不会被执行
所以console.log(b) 的值为undefined同理c的值也为undefined,当执行了a=10后,console.log(a)的值也变成了10
不过需要注意的是f=123,由于没有声明就开始赋值,就变成了全局对象里面的f,所以全局gobal对象里面的f的值为123