在JavaScript中存在一种预编译的机制,这也是Java等一些语言中没有的特性,也就正是因为这个预编译的机制,导致了js中变量提升的一些问题,下面这两句话能解决开发当中一部份问题,但不能解决所有问题,还有一些问题是你必须通过学习预编译才能解决的。
预编译分为全局预编译和局部预编译,全局预编译发生在页面加载完成时执行,而局部预编译发生在函数执行的前一刻。
js运行三部曲:
语法分析
预编译
解释执行
函数声明整体提升:把函数声明提在最前面
变量 声明提升:会把声明提升到最前面 (var a)
1.imply global暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有
全局对象是window
eg:a = 123;
eg:var a = b = 123;
2.一切声明的全局变量,全是window的属性
eg:var a = 123; ==> window.a = 123
预编译发生在函数执行的前一刻
预编译:
四部曲:
1.创建AO 对象 (Activation Object,执行器上下文)
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3.将实参值和形参统一
4.在函数体里面找函数声明,值赋予函数体
eg: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);
步骤:
1.AO
2.AO{
a:undefined,
b:undefined
}
3.AO{
a:1,
b:undefined
}
4.AO{
a:function a() {},
b:undefined,
d:function d() {}
}
输出结果:function a() {}
123
123
function () {}
eg2: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
2.AO{
a:undefined,
b:undefined,
c:undefined,
}
3.AO{
a:1,
b:undefined,
c:undefined,
}
4.AO{
a:1,
b:function b() {}
c:undefined
d:function d() {}
}
输出结果为1,2,2
全局:1.生成一个GO对象Global Object
2.GO{
}
找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3.在函数体里面找函数声明,值赋予函数体
GO === window
eg:
var a = 123;
function fn(a) {
console.log(a);
}
fn();
全局生成GO
GO{
a:undefined;
fn:undefined
}
GO{
a:123,
fn:function fn(){...}
}
此时执行fn(),局部生成AO
AO{
}
因为AO里没有东西,所以console.log(a)回向GO中去找,输出为123
eg:
1.function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
console.log(bar());
2.console.log(bar());
function bar() {
foo = 10;
function foo(){}
var foo = 11;
return foo;
}
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);
步骤:
GO{
a:100,
demo:function() {},
}
执行demo(1),执行demo函数
AO{
e:undefined,
b:undefined,
c:undefined,
a:undefined
}
AO{
e:1,
b:undefined,
c:undefined,
a:undefined
}
AO{
e:2,
b:undefined,
c:undefined,(现在规定if里不能定义函数,所以不是function)
a:10
}
函数里的console.log(e):2
console.log(b):undefined
console.log(c):undefined
console.log(a):10
GO{
a:100,
demo:function() {}
f:123
}
函数外的console.log(a):100
console.log(f):123
(window.foo || (window.foo = 'bar'));
==>window.foo = bar