var变量声明提升
var提升的是变量的“声明”,不是变量的“赋值”。
“提升”指把“声明”提升到各层作用域的顶端执行。
分清楚变量的“声明”、“定义”、“初始化”之间的区别。
Kevin 认为 js中的“声明”=“定义”+初始化为“undefined”
Kevin 认为 js中的定义提升,是let、var都能做到的,就是在js引擎真正解释整份代码文件前,会把let、var定义的变量,预先写入各层作用域的命名空间中。但变量声明提升(定义+初始化为undefined)只有var可以做到。因此会有以下现象:
console.log(a); // 报错,a未定义
console.log(a); // 报错,a未初始化前,不能使用a
let a = 1;
let a;
console.log(a); // undefined
console.log(a); // undefined
var a=1;
第二段代码中,let虽然写在第二行,但还是对第一行造成影响,符合一开始的推论:let对变量a做了定义,但是没有初始化为undefined。
为证实推论,进一步验证其在函数局部作用域中的表现差异
var a = 1;
function fn(){
console.log(a); // 1
}
fn();
var a = 1;
function fn(){
console.log(a); // 报错,a未初始化前,不能使用a
let a = 2;
}
fn();
var a = 1;
function fn(){
console.log(a); // undefined
var a = 2;
}
fn();
发现的确,只要在一个局部作用域里的任何位置let或var定义变量,这种定义都会被提升,但只有var提升的同时还做了初始化undefined。
有了上面的推论,下方的实验结果就很好理解了
var a = 1;
console.log(a); // 1
function fn(){
console.log(a); // undefined
var a=2;
console.log(a); // 2
}
var a = 100;
fn();
console.log(a); // 100
var a;
console.log(a); // 100
var a=200;
console.log(a); // 200
- 可以理解为:声明=定义+初始化为undefined
- 声明与赋值无关
- 变量的定义无论出现在该层作用域的哪一行,都会对整个作用域发生影响(let、var表现一致)
- var的变量声明提升,比let多了一个初始化为undefined的过程
- 声明提升,但声明连带的赋值不提升(var a=100;),赋值语句原来在哪行发生,还是在哪行发生。
- 已经用var声明的变量,再次不赋值地声明(var a;),并不会对其原来的值造成影响;
- 已经用var声明的变量,再次用赋值来声明(var a=200;),则可以理解为仅仅是在该行进行一次新的赋值,而没有所谓的重新定义与初始化。
PS:另外同一层作用域,var可以对同一变量名重复多次声明,但let不行。
var 的变量声明如果是在函数内部(在函数内部变量提升),则函数外部仍旧是没有定义这个变量的;但如果var的变量声明是在函数外部的(无论是 for 语句中 还是某个语句块),则是在全局作变量提升的,全局都能访问到这个变量。
{ var a=1; } console.log(a); // 1
function abc(){ var aa = 1; } abc(); console.log(aa); // 报错 aa 未定义。