前言:
let 的用法类似于 var ,但是 let 只在所在的代码块内有效,所以我们一般使用 let 替代 var 。而 const 用来声明常量。
一、let命令
1. 块级作用域
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
{ // 块级作用域
let a = 10;
var b = 1;
}
console.log(a); // ReferenceError: a is not defined.
console.log(b); // 1
上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效,var变量的声明是全局有效。
特别是在我们使用循环时,let 相较于 var 的优点显而易见,用let声明 在某一作用域下的变量 不会污染全局
for (var i = 0; i < 3; i++) {
console.log("循环体中:"+i);
}
console.log("循环体外:"+i); // var声明会污染全局,所以在某一作用域下声明变量,我们多用let声明
console.log('--------------');
for (let j = 0; j < 3; j++) {
console.log("循环体中:"+j);
}
console.log("循环体外:"+j); // ReferenceError: a is not defined.
2. 不存在变量提升
// var 的情况
console.log(foo); // 正常运行,控制台输出 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错,Uncaught ReferenceError: bar is not defined
let bar = 2;
在JavaScript编译的过程中,内部会自动帮我们变量提升,所以实际上代码的执行顺序如下:
// var 的情况
var foo;
console.log(foo); // 正常运行,控制台输出 输出undefined
foo = 2;
// let 的情况
console.log(bar); // 报错,Uncaught ReferenceError: bar is not defined
let bar= 2;
3. 暂时性死区
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
(1)只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123;
if (true) {
tmp = 'abc'; // Uncaught ReferenceError: tmp is not defined
let tmp;
}
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。
有些死区不太容易发现
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 报错
调用bar函数之所以报错(某些实现可能不报错),是因为参数x默认值等于另一个参数y,而此时y还没有声明,属于“死区”。如果y的默认值是x,就不会报错,因为此时x已经声明了。
4. 不允许重复声明
// 报错 Identifier 'a' has already been declared
function func() {
let a = 10;
var a = 1;
}
// 报错 Identifier 'a' has already been declared
function func() {
let a = 10;
let a = 1;
}
因此,不能在函数内部重新声明参数。
function func(arg) {
let arg;
}
func() // 报错 Identifier 'arg' has already been declared
function func(arg) {
{
let arg;
}
}
func() // 不报错
二、const命令
const 的特性和上述的 let 的特性 基本一致,不过多赘述
** const特点 **
和 var,let 不同,const必须有初始值 ,而且 一旦定义,则不可改变 ,否则会报错
const NAME = "MIKASA";
console.log(NUM); // MIKASA
NAME = "JACK" // 报错,Uncaught TypeError: Assignment to constant variable. 常量,不可改变
const AGE; // 报错,Uncaught SyntaxError: Missing initializer in const declaration. 必须有初始值
const的本质(重要***)
const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
(1)对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。
(2)对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。