var、let 及 const 区别
var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用 var 在全局作用域下声明变量会导致变量

对于这个问题,我们应该先来了解提升(hoisting)这个概念
var
js
console.log(a) // undefined
var a = 1
从上述代码中我们可以发现,虽然变量还没有被声明,但是我们却可以使用这个未被声明的变量,这种情况就叫做提升,并且提升的是声明。
对于这种情况,我们可以把代码这样来看
js
var a
console.log(a) // undefined
a = 1
当函数和变量重名,变量的提升更高,函数的提升在变量的下面
js
var a = 10;
var a = function (){}
console.log(a) // ƒ (){}
var b = 20;
function b(){}
console.log(b) // 20
解读
js
var a;
a = function (){};
var b;
function b(){};
b = 20;
函数提升
函数提升所指的形式:function fn(){......}(必须是函数声明的形式,不能是函数表达式的形式)
所有使用function声明的函数,都会整体提升,只要当前作用域内声明了函数,在任何位置都可以使用,赋值式创建函数,提升的声明,不是。
当函数和变量重名,变量的提升更高,函数的提升在变量的下面
接下来我们再来看一个例子
js
var a = 10
var a
console.log(a)
对于这个例子,如果你认为打印的值为 undefined 那么就错了,答案应该是 10,对于这种情况,我们这样来看代码
js
var a
var a
a = 10
console.log(a)
到这里为止,我们已经了解了 var 声明的变量会发生提升的情况,其实不仅变量会提升函数也会被提升
js
console.log(a) // ƒ a() {}
function a() {}
var a = 1
对于上述代码,打印结果会是 ƒ a() {},即使变量声明在函数之后,这也说明了函数会被提升,并且优先于变量提升
循环内变量过度共享
js
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i) // 3 3 3
}, 1000);
}
for(var i=0;i<=10;i++){
var sum=0;
sum+=i;
}
console.log(sum) // 10
let
let拥有块级作用域,一个{}就是一个作用域,也就是let声明块级变量,即局部变量;
let在其作用域下面不存在变量提升;
let在其作用域中不能被重复声明(函数作用域和块级作用域)
js
let n = 10;
if(true){
let n = 50;
}
console.log(n);//10
let在同一个作用域下不允许进行重复变量声明,否则直接报错
js
(function(){
let test1 = "let";
var test2 = "var"
let test1 = "let changed";//Uncaught SyntaxError: Identifier 'lTest' has already been declared
var test2 = "var changed";
console.log(test1);
console.log(test2);
})();
const
const用来声明常量,一旦声明,其值就不可以更改,而且必须初始化
js
var a = 1
let b = 1
const c = 1
const obj = {a:1}
obj.a = 10
console.log(window.a) // 1
console.log(window.b) // undefined
console.log(window.c) // undefined
console.log(obj.a) // 10 因为对象是引用类型 储存在堆中
总结
var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用
var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会
let 和 const 作用基本一致,但是后者声明的基本类型变量不能再次赋值