let 命令
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是有以下几个主要的区别:
1. let声明的变量,只在let命令所在的代码块内有效。如:
{
let a = 1;
var b = 2;
}
a // ReferenceError: a is not defined.
b // 2
let实际上为 JavaScript 新增了块级作用域。如:
function f() {
let a = 1;
if (true) {
let a = 10;
}
console.log(a); // 1
}
结果会输出1,表明
外层代码块不受内层代码块的影响。如果把let换成var,则结果会是10。
console.log(a); // ReferenceError: a is not defined
let a = 1;
而var命令会存在变量提升现象。即所有的声明都会被提升到各自作用域的最顶端。js会把类似 var a = 1 ;的声明语句拆分成 var a; 和 a = 1;两部分。第一个定义声明是在代码预编译阶段进行的,而第二个赋值声明是在执行阶段进行的。请看下面的代码:
console.log(a); // undefined
var a = 2;
这段代码等同于下面的代码,所以会输出undefined,而不会报错。
var a;
console.log(a);
a = 2;
这也就解释了为什么下面的代码结果会输出2。
a = 2;
var a;
console.log( a );//2
不仅变量声明会被提升,函数声明也会被提升。而且函数提升优先级会高于变量提升。如:
a(); // 1
var a;
function a() {
console.log( 1 );
}
a = function() {
console.log( 2 );
};
上面的代码会输出1,而不是2或者undefined。以上代码等同于:
function a() {
console.log( 1 );
}
a(); // 1
a = function() {
console.log( 2 );
};
下面来看一个之前让我困惑了很久的代码(代码摘自阮一峰老师的ECMAScript 6 入门):
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 tmp;
function f() {
var tmp ;
console.log(tmp);
if (false) {
tmp = 'hello world';
}
}
tmp = new Date();
f(); // undefined
函数内部的tmp变量提升到了函数作用域顶部,所以覆盖了外层的tmp变量,输出undefined。
3. let不允许在相同作用域内,重复声明同一个变量。如:
// Identifier 'a' has already been declared
function f() {
let a = 1;
var a = 2;
}
// Identifier 'a' has already been declared
function f() {
let a = 1;
let a = 2;
}
而 var 可以重复声明变量,且会覆盖前一个的值。
const 命令
ES6中的const命令声明一个只读的常量。一旦声明,常量的值就不能改变,所以一旦声明变量,就必须立即初始化。const命令和let命令一样,只在声明所在的块级作用域内有效,且不存在变量提升。如下面代码就会报错:
const a = 1;
a = 2;// TypeError: Assignment to constant variable.
用const命令声明一个对象又区别于声明简单类型的数据。对复合类型的数据来说,变量指向的内存地址中保存的仅是指向对象的一个指针。const只能保证这个指针是固定的,但是对象本身是可变的,所以可以为其添加新属性或方法。如:
const person = {};
// 为 person 添加一个属性,可以成功
person.name = 'amy';
console.log(person.name); // amy
// 将 person 指向另一个对象,就会报错
person = {}; //TypeError: Assignment to constant variable.