ES6-let 和 const 命令

参考文章: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

上面代码正确运行,输出了 3abc。这表明函数内部的变量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; // 不报错
  }
}

二、块级作用域

  • 为什么需要块级作用域
    • 变量提升导致变量覆盖
    • 用来计数的循环变量泄露为全局变量
  • letJavaScript 新增了块级作用域。
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 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。

你可能感兴趣的:(ES6-let 和 const 命令)