var let const
const 在声明变量时必须初始化(声明变量的同时并赋值即初始化),var和let可以不用
// var
var a
a = 1
console.log(a) // 1
// let
const b
b = 2
console.log(b) //Uncaught SyntaxError: Missing initializer in const declaration
//const
const c
c = 3
console.log(c) // 3
var存在变量提升,let和const不存在变量提升
// 1.var
aaa = 1
var aaa;
console.log(aaa) // 1,证明变量有提升
// 2.let
bbb = 1
let bbb
console.log(bbb) // 报错 Uncaught ReferenceError: Cannot access 'bbb' before initialization
// 3、const
ccc = 1;
const ccc; // 这一行就已经报错 Uncaught SyntaxError: Missing initializer in const declaration
console.log(ccc)
let和const存在暂时性死区
只要块级作用域内存在let、const
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。总之,在代码块内,使用let、const
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)
let tmp = 123
//代码块中的tmp将不受外部的tmp影响,形成TDZ
if(true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123
console.log(tmp) // 123
}
//上面代码中,在let命令声明变量tmp之前,都属于变量tmp的“死区”。
let和const不允许重复声明
// 不会报错(外面的a和{}里的a不在同一作用域里)
let a = 18;
if(true) {
let a = 20;
}
// 会报错(在同一作用域{}内)
if(true) {
let a = 18;
let a = 20;
}
const声明一个只读的常量,且必须初始化
const 声明一个只读
的常量。一旦声明,常量的值就不会改变。这意味着,const一旦声明变量,就必须立即初始化
,不能留到以后赋值。
const PI = 3.1415;
console.log(PI); //3.1415
PI = 3.14; //TypeError: Assignment to constant variable.
为什么需要块级作用域
场景一:内层变量可能会覆盖外层变量
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
场景二:用来计数的循环变量泄露为全局变量
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。可以把var改成let就可以解决问题。
总结:
- var声明存在变量提升,let和const不存在变量提升
- let、const都是块级局部变量,在该块级作用域之外将不能被访问
- 同一作用域下let和const不能声明同名变量而var可以
const
:如果声明了一个常量为json对象类型,那么这个常量里面的对象属性
可以更改和添加。