参考文章:let 和 const 命令
本书中提到 ES6
的地方,一般是指 ES2015
标准,但有时也是泛指“下一代 JavaScript
语言”。
一、let 命令
-
let
命令所声明的变量,只在let
命令所在的代码块内有效。
// 在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
-
for
循环的计数器,就很合适使用let
命令。
下面的代码如果使用var
,最后输出的是10
。如果使用let
,声明的变量仅在块级作用域内有效,最后输出的是 6
。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
- 另外,
for
循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代码正确运行,输出了 3
次abc
。这表明函数内部的变量i
与循环变量i
不在同一个作用域,有各自单独的作用域。
-
不存在变量提升
-
var
命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined
。 -
let
命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
-
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
- 暂时性死区
在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。(temporal dead zone
,简称 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
不允许在相同作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
二、块级作用域
- 为什么需要块级作用域
- 变量提升导致变量覆盖
- 用来计数的循环变量泄露为全局变量
-
let
为JavaScript
新增了块级作用域。
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
这表明let
定义变量,外层代码块不受内层代码块的影响。如果两次都使用var
定义变量n
,最后输出的值才是 10
。
- 块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(
IIFE
)不再必要了。
// IIFE 写法
(function () {
var tmp = ...;
...
}());
// 块级作用域写法
{
let tmp = ...;
...
}
三、const
命令
-
const
声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
-
const
声明的变量不得改变值,这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值。
const foo;
// SyntaxError: Missing initializer in const declaration
-
const
的作用域与let
命令相同:只在声明所在的块级作用域内有效。
if (true) {
const MAX = 5;
}
MAX // Uncaught ReferenceError: MAX is not defined
-
const
命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
if (true) {
console.log(MAX); // ReferenceError
const MAX = 5;
}
-
const
声明的常量,也与let
一样不可重复声明。
var message = "Hello!";
let age = 25;
// 以下两行都会报错
const message = "Goodbye!";
const age = 30;
-
const
简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
网友评论