全局变量的知识补充
function func() {
a = "a";
var b = "b";
}
func(); //函数执行后,变量声明和赋值才能生效
console.log(a); //a未经声明就赋值,属于全局变量,在函数外部可被访问
console.log(b); //b是局部变量,在函数外部不能被访问
window.变量名
的方式访问var a = 123; //等同于在window对象上加上了一个属性:window{ a : 123 }
//下面两种访问方式的结果都是一样的
console.log(a);
console.log(window.a);
什么是预编译?
JavaScript的执行过程大致分为三步:
预编译是JavaScript执行过程中的一个重要步骤
预编译会造成什么现象?
在其他高级语言中,基本上变量和函数都是先声明再使用,如C/C++中,变量和函数的声明一定是写在变量和函数被使用之前,否则就会报错。
而在JavaScript中,变量和函数在声明之前被使用时,不会报错,且函数在声明之前被使用是完全允许的。但不是说变量和函数不声明就可以使用,还是要声明才能正常使用的,只不过声明可以写在使用之后。这就是JavaScript预编译造成的现象。
下面四段代码可以进行演示预编译造成的现象:
var a = 123;
console.log(a);
很正常的一段代码,输出结果为:123
?
console.log(a);
var a = 123;
不会报错,但执行结果可能并不是我们想要的,输出结果为:undefined
?
function test(){
console.log("123");
}
test();
同样是一段很正常的代码,输出结果为:"123"
?
test();
function test(){
console.log("123");
}
不会报错,且函数正常执行,输出结果为:"123"
?
以上是预编译所造成的现象,后面将对这些现象进行解释
预编译的过程可以概括为四个步骤:
AO{ }
AO{
形参名:undefined,
变量名:undefined
}
AO{
形参名:实参值,
变量名:undefined
}
AO{
形参名:实参值,
变量名:undefined,
函数名:函数体
}
注:AO对象里不会出现多个相同名字的属性。若变量名、形参名和函数名一样时,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); //输出结果为fucntion(){}
}
fn(1);
在上述代码的预编译过程及执行过程的分析如下:
预编译阶段:
AO{}
AO{
a: undefined,
b: undefined
}
AO{
a: 1,
b: undefined
}
AO{
a: function a(){},
b: undefined,
}
函数执行阶段:
console.log(a);
语句:从AO对象里读取a,输出结果为function a(){}
var a = 123;
语句:此时a已被声明,因为形参里也有一个a,所以a已经被隐式地声明过了。这里略过声明,直接执行赋值操作,将AO对象里的a赋值为123:AO{
a: 123,
b: undefined
}
console.log(a);
语句:再次从AO对象里读取a,输出结果为123
function a(){}
语句:此语句直接跳过,不执行,因为在预编译阶段已经完成了函数声明(在AO对象里)console.log(a);
语句:再次从AO对象里读取a,输出结果为123
var b = function(){}
语句:这里的声明已经在预编译阶段完成,所以跳过声明,直接执行赋值操作,将AO对象里的b赋值为function(){}
:AO{
a: 123,
b: function(){}
}
console.log(b);
语句:从AO对象里读取b,输出结果为function(){}
在全局作用域里同样也存在预编译,其过程和函数执行过程中的类似,只是少了"将实参值和形参值统一"这一步,因为全局作用域里不存在参数这个概念。
还有一点区别就是,全局作用域里生成的不是AO对象而是GO对象(Global Object),其作用与AO对象的一致。
GO对象其实就等效于window对象。
就是函数作用域和全局作用域同时存在时预编译的过程
此时,先生成GO对象并完成全局作用域的预编译过程,然后再生成AO对象并完成函数作用域的预编译过程。
在函数执行阶段,若有函数体里的局部变量与某一个全局变量重名,则优先访问函数体里的变量值(即AO对象里对应的属性值)
原文:https://www.cnblogs.com/xiaowus/p/12824675.html