变量提升与函数提升
变量提升:是变量声明提升,变量赋值没有提升。var a = 123,这是变量var a提升到最前面。
函数声明整体提升:函数不管写在哪里,都会被提升到逻辑的最前面。所以不管在哪里调
用,本质上都是在声明后调用。
imply global暗示全局变量
任何变量未经声明就赋值,此变量就归全局对象window所有。window就是全局的域。
function test() { var a = b = 123;//首先给b赋值12-->window.b = 123, 然后声明a,在把b的值赋给a, a=123; console.log(a);//123 局部变量a console.log(b);//123 函数内可以访问全局变量b } test(); console.log(b)//123 全局变量b console.log(a)//报错,因为全局上没有声明a,未经声明就访问就会报错! function demo () { var c = 123; } demo(); console.log(window.c);//打印undefined,window是全局对象,访问一个对象没有的属性就是 undefined console.log(c);//会报错, 变量c的作用域是函数内,在全局是没有声明这个变量的,这种访问方式是访问一个未声明的变量,所以就报错了。
预编译:解决执行顺序问题,预编译发生在函数执行的前一刻。
函数预编译四部曲
1.创建OA(Activation Object)对象 (执行期上下文,理解作用域,函数产生的执行空间库)。
2.找形参和变量,将其作为AO属性名,值为undefined。
3.将形参和实参统一(把实参传入到形参里)。
4.在函数体里找函数声明,值赋予函数体 (执行过程过中搜索变量,先看自己的AO,再看GO)
示例代码
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)
1. AO: {//找形参和变量. GO: {}
a: undefined,
b: undefined,
c: undefined,
}
2. AO: {//将形参和实参统一
a: 1,
b: undefined,
c: undefined
}
3. AO:{//找函数声明
a: 1,
b: function(){},
d: function(){},
c: undefined,
}
4.执行console.log(a); 输入1
执行c=0
AO: {
a: 1,
b: function(){},
d: function(){},
c:0,
}
执行var c; 不用管,因为c已经在AO中了。
执行a = 3,b = 2;
AO:{
a: 3,
b: 2,
d: function(){},
c:0,
}
执行console.log(b); 输出 2;
function b() {};function d() {}; 函数声明 不用管。
再次执行console.log(b); 输入2;
答案:1, 2, 2
一旦有重名的,既有a变量,又有a函数,又在第一条语句访问a, 那么a一定是函数。(因为函数声明在后一步,会覆盖变量声明)示例代码
function test(a, b) {
console.log(a);
console.log(b);
var b = 234;
console.log(b);
a = 123;
console.log(a);
function a() {};
var a;
b = 234;
var b = function (){}
console.log(a);
console.log(b);
}
test(1);
1. AO:{
a:undefined,
b:undefined,
}
2. AO: {
a:1,
b:undefined,
}
3. AO: {
a: function a(){},
b: undefined
}
4.执行console.log(a) 输出: function a(){}
执行console.log(b) 输出: undefined
执行var b = 234;
AO: {
a: function a(){},
b: 234,
}
执行console.log(b); 输出 234
执行a = 123;
AO: {
a: 123,
b: 234,
}
执行console.log(a); 输出: 123
执行b=234
AO: {
a: 123,
b: 234,
}
执行var b = function (){}
AO: {
a: 123,
b:function(){},
}
执行console.log(a); 输出123,
执行console.log(b); function(){}
全局预编译三部曲
1.生成一个GO对象,Golbal Object(window 就是GO)
2.找形参和变量声明,将形参和变量作为GO的属性名,值为undefined
3.在函数体里找函数声明,值赋予函数体
全局预编译
console.log(a);//undefined 变量声明提升
var a = 123;
//例子2
console.log(a);//function a(){} //函数声明整体提升
var a = 123;
function a() {};
GO: {
a:undefind,//找变量
}
GO: {
a: function a(){} //找函数声明
}
执行console.log(a) 输出function a(){}
先有GO 再有AO
在全局,先生成GO,在函数执行前一刻生成AO
console.log(test);
function test(test) {
console.log(test);
var test = 234;
console.log(test);
function test() {};
}
test(1);
var test = 123;
1.生成GO: {//有变量test
test: undefined,
}
2.GO: {//有函数声明
test: function test(){}
}
3.执行console.log(test) //在GO找test 输出 function test(){}
4.执行test(1) 生成AO
AO: {
test: undefined,//有变量test
}
AO: {
test: 1, //实参形参统一
}
AO: {
test: function test(){}, //有函数声明
}
5.执行console.log(test) //在AO中找,就近原则, 没有才去GO中找 输出 function test(){}
6.执行var test = 234;
AO : {
test: 234,
}
7.执行console.log(test); // 输出 234