1. var存在变量提升
var a = 99; // 全局变量a f(); // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。 console.log(a); // a=>99, 此时是全局变量的a function f() { console.log(a); // 当前的a变量是下面变量a声明提升后,默认值undefined var a = 10; console.log(a); // a => 10 } // 输出结果: undefined 10 99 //原代码等价于 var a; function f() { console.log(a); var a = 10; console.log(a); } a = 99; f(); console.log(a);
2. var重复声明不会报错
var a = 1; var a = 2; //编译通过
3. var 只有函数作用域和全局作用域,let 有 块状作用域
{ var i = 9; } console.log(i); // 9 { let j = 9; } console.log(j); // undifined
4. 关于for循环
for循环每次的循环体是一个块级作用域,即对于利用setTimeout循环输出循环变量那段代码(如下):
for (var i = 0; i < 2; i++) { setTimeout(() => { console.log(i); }, 0); }
可以理解为
{ var i = 0 if (i < 2) { setTimeout(() => { console.log(i); }, 0); i++; } } { var i = 1 if (i < 2) { setTimeout(() => { console.log(i); }, 0); i++; } } { var i = 2 if (i < 2) { setTimeout(() => { console.log(i); }, 0); i++; } }
由于var不存在块级作用域且可以重复声明,根据事件循环机制可以知道输出是2,2
而当把var 替换成 let之后,代码可以理解成:
{ let i = 0 if (i < 2) { setTimeout(() => { console.log(i); }, 0); i++; } } { let i = 1 if (i < 2) { setTimeout(() => { console.log(i); }, 0); i++; } } { let i = 2 if (i < 2) { setTimeout(() => { console.log(i); }, 0); i++; } }
每个块级作用域中的i都是独立的,互不影响,因此保留了当前循环体的i值,输出为1,2
扩展:
函数声明:
function fun(){}也存在变量提升,且当与var声明的变量重名时,函数优先级更高。
console.log(a); function a(){}; var a = 1; console.log(b); var b = 1; function b(){}; //输出 [Function: a] [Function: b]
var a = function(){}存在变量提升,但是提升的a是一个变量而非函数。
a(); a = 1; var a = function(){ console.log("function"); } //报错 TypeError: a is not a function
b(); b = 1; function b(){ console.log("function"); } //输出 function