let
let 声明的变量只在let所在的代码快内有效
块级作用域
在javascript中只有全局作用域和函数作用域,并不存在块级作用域
{
var a = 0;
let b = 1;
}
console.log(a);//0
console.log(b);//Uncaught ReferenceError: b is not defined
var声明的变量由于不存在块级作用域所以可以在全局环境中调用,而let声明的变量由于存在块级作用域所以不能在全局环境中调用。
不允许重复声明
var 可以声明多次,let 只能声明一次
{
var m = 1;
var m = 2;
let n = 3;
let n = 4;
console.log(m);
console.log(n);
}
结果直接报错:Uncaught SyntaxError: Identifier 'n' has already been declared
不存在变量提升
使用let不会像使用var一样存在一个变量提升的现象。
变量提升:即变量可以在声明之前使用,值为undefined
{
console.log(x);//undefined
var x = 10;
console.log(y);//报错 Uncaught ReferenceError: Cannot access 'y' before initialization
let y = 20;
}
暂时性死区
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
{
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
};
}
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错
const
const 声明一个只读的常量,一旦声明,常量的值就不能改变。意味着,一旦声明必须初始化,否则会报错。
{
const a = 1;
a = 3;
console.log(a);
}
结果报错:Uncaught TypeError: Assignment to constant variable.
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。