ES6新增加了两个重要的 JavaScript 关键字: let 和 const。它们和var一样,都是用来声明变量。
下面介绍一下它们的区别,以及如何正确使用。
一、let
- 变量不能重复声明
let name = '周杰伦';
let name = '陈奕迅'; // Identifier 'name' has already been declared
- 块级作用域
let 是在代码块内有效,var 是在全局范围内有效。
{
let x = 0;
var y = 0;
}
console.log(x); // Uncaught ReferenceError: x is not defined
console.log(y); // 0
- 不存在变量提升
let不存在变量提示,但是var存在。
console.log(song); // Uncaught ReferenceError: Cannot access 'song' before initialization
let song = '晴天';
console.log(name); // undefined
var name = "周杰伦";
- 不影响作用域链
{
let name= '周杰伦';
function fn() {
console.log(name); // 此函数作用域链没有name变量,会向上一级的作用域链寻找name变量
}
fn(); // 周杰伦
}
let推荐使用场景
在for循环中,推荐使用let,举个栗子:
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
})
}
console.log(window.i); // 10
// 输出十个 10
for (let j = 0; j < 10; j++) {
setTimeout(function(){
console.log(j);
})
}
// 输出 0123456789
对上面的代码作出解释:
- 变量 i 是用 var 声明的,在全局范围内有效,所以全局中只有一个变量 i,当我们用 console.log(window.i) 来检验 i 时,发现 i 为10。每次循环时,setTimeout 定时器里面的 i 指的是全局变量 i ,而循环里的十个 setTimeout 是在循环结束后才执行,所以会输出十个 10。
- 变量 j 是用 let 声明的,当前的 j 只在本轮循环中有效,每次循环的 j 其实都是一个新的变量,所以 setTimeout 定时器里面的 j 其实是不同的变量。(若每次循环的变量 j 都是重新声明的,如何知道前一个循环的值?这是因为 JavaScript 引擎内部会记住前一个循环的值)。
二、const
- 一定要赋初始值
const声明一个变量,一旦声明必须初始化,否则会报错。但是var和let声明变量后不赋值,只会报 undefined
const NAME = '周杰伦';
console.log(NAME); // 周杰伦
const SONG; // Uncaught SyntaxError: Missing initializer in const declaration
- 常量的值不能修改,修改会报错
一般情况下,我们将值不会改变的变量叫做常量,所以我们会习惯性用const来声明一个常量,因为const声明的变量一般情况下是不允许修改的(特殊情况下除外,例如const声明一个数组或者对象,如下第4点)。
const NAME = '周杰伦';
NAME = '陈奕迅'; // Uncaught TypeError: Assignment to constant variable
- 块级作用域
const同样存在块级作用域。
{
const AGE = 18;
}
console.log(AGE); // AGE is not defined
- 对于数组和对象的元素修改,不算对常量的修改,不会报错
const TEAM = ['asd', 'gsd', 'hs'];
TEAM.push('asf'); // 可以对数组的元素进行修改,因为常量指向的地址没有改变
TEAM = 100; // 此时常量指向的地址以及发生改变,会报错 Uncaught TypeError:Assignment to constant variable
const推荐使用场景
当声明一个值不允许改变的变量的时候,应该使用const。
声明数组或者对象的时候,推荐使用const,这是一个比较稳妥的方法。