预编译及变量提升

预编译及变量提升

变量提升的概念:
// 变量提升:将【当前作用域】下所有声明的变量;提升到作用域最顶端
// 变量提升:声明提升,赋值不提升。
函数提升的概念:
// 将函数本体提升到作用域最顶端
// 将所有变量提升当前作用域最顶端
// 当函数名与变量名重复时候,变量赋值,会将函数本体覆盖

众所周知javascript是解释性语言,主要特点为解释一行执行一行。

而在js运行时会进行三件事:1语法分析 2.预编译 3.解释执行

语法分析会在代码执行前对代码进行通篇检查,以排除一些低级错误

预编译发生在代码执行的前一刻

解释执行顾名思义就是执行代码

我先给大家举几个预编译的小例子:

    var a = 123;

console.log(a);

此时他返回的值会是123;

但如果我们调换位置:

      console.log(a);

      var a = 123;      

      我们得到的结果便会是undefined。(由于js解释性语言的原因,先执行console.log,而由于预编译的原因浏览器并不会报错)

如果我们在次尝试不定义变量直接获取:

            console.log(a);  此时我们会发现浏览器会进行报错。//Uncaught ReferenceError: a is not defined

                                                                                                           这条语句提示我们a没有定义

到这里有些人会有疑问为什么在console.log前,后和不定义a会有如此大的差别,这就是预编译起到的作用

预编译发生在函数执行的前一刻,过程如下:

创建AO对象,执行期上下文(后面更新关于执行期上下文详解)。
寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
将形参和实参相统一,即更改形参后的undefined为具体的形参值。
寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。

实例

我们先来看下面这段代码:
function fn(a){
console.log(a);
var a = 123;
console.log(a);

function a(){};
console.log(a);

var b = function(){};
console.log(b);

function d(){};

}

//调用函数
fn(1);

创建AO对象

AO{
//空对象
}
//复制代码
//找形参和变量声明

AO{
a : undefined,
b : undefined
}
//复制代码
//形参和实参相统一

AO{
a : 1,
b : undefined
}
//复制代码
//找函数声明

AO{
a : function a(){},
b : undefined,
d : function d(){}
}
//复制代码预编译环节就此结束,此时的AO对象已经更新为:
AO{
a : function a(){},
b : undefined,
d : function d(){}
}
//复制代码函数开始逐行顺序执行:
function fn(a){
console.log(a);// 输出functiona(){}
var a = 123;//执行到这里重新对a赋,AO对象再一次更新
console.log(a);// 输出123

function a(){};//预编译环节已经进行了变量提升,故执行时不在看这行代码
console.log(a);// 输出123

var b = function(){};//这个是函数表达式不是函数声明,故不能提升,会对AO中的b重新赋值
console.log(b);//输出function(){}

function d(){};

}
//复制代码至此,函数执行完毕,销毁AO对象。
//我们再来看几个例子,熟悉函数的预编译过程。
//示例一:
function test (a,b){
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b(){};
function d(){};
console.log(b);
}
//调用函数
test(1);
//复制代码它的AO创建过程如下(此处省略创建空AO对象的部分,下文同):
AO1{
a : undefined,
b : undefined,
c : undefined
}

AO2{
a : 1,
b : undefined,
c : undefined
}

AO3{
a : 1,
b : function b(){},
c : undefined,
d : function d(){}
}
//复制代码至此预编译环节完成,开始执行:
function test (a,b){
console.log(a); //输出1
c = 0; //给AO对象中的c重新赋值0
var c;//预编译环节变量提升,不再读此行代码
a = 3;//给AO对象中的a重新赋值3
b = 2;//给AO对象中的b重新赋值2
console.log(b);//输出2
function b(){};//预编译环节变量提升,执行时不再读这行代码
function d(){};//预编译环节变量提升,执行时不再读这行代码
console.log(b);//输出2
}
//调用函数
test(1);

示例

GO2{
b : 123;
}
AO2{
a : 123;
}
//复制代码示例三 :
console.log(test);
function test(test){
console.log(test);
var test = 234;
console.log(test);
function test(){};
}
test(1);
var test = 123;
//复制代码我们来看它的预编译过程:
//执行前(页面加载完成时)生成GO对象
GO1{
test : undefined
}
GO2{
test : function(){}
}

//输出 function test(){…}

//执行test()前生成它的AO对象
AO1{
test : undefined
}
AO2{
test : 1
}
AO3{
test : function test(){}
}

//预编译结束开始执行test(1);
AO4{
test : 234
}
//输出234
//复制代码示例四:
function demo(){
console.log(b);
if(a){
var b = 100;
}
console.log(b);
c = 234;
console.log©;
}
var a;
demo();
a = 10;
console.log©;
//复制代码我们来看它的预编译过程:
//首先是全局对象GO
GO1{
a : undefined
}
G02{
a : undefined,
demo : function demo(){}
}
//执行demo()前预编译,由于demo中的c未声明就使用故为全局对象

//输出undefined
GO3{
a : undefined,
demo : function demo(){}
c : undefined
}
//此时a还是undefined,故不执行if()代码块
//输出还是undefined
GO4{
a : undefined,
demo : function demo(){}
c : 234;
}
//输出234
GO5{
a : 10,
demo : function demo(){}
c : 234;
}
//输出234

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值