车栈

ES2015入门系列2-let和const

ES2015 新增了两个变量修饰关键字:

  • let
  • const

它们都是块级别的,那什么是块?简单的来说,块就是一组花括号中间的部分。

  • Var

为了理解let我们先从var说起,如下代码:

function checkStatus(status) {
  if (status) {
    var statusLabel = 'ok';
    console.log(statusLabel);
  } else {
    console.log(statusLabel);
  }
}
checkStatus(true);
checkStatus(false);

在 Chrome Console 中运行后,获得结果:

ok
undefined

我们在false条件中加入一行代码:

function checkStatus(status) {
  if (status) {
    var statusLabel = 'ok';
    console.log(statusLabel);
  } else {
    console.log(statusLabel);
    console.log(abc);//执行后会输出: Uncaught ReferenceError: abc is not defined(…)
  }
}
checkStatus(true);
checkStatus(false);

对于初次接触JavaScript的后端程序员来说,会觉得非常奇怪,在传入false的时候为什么得到的statusLabel是undefined而不是变量未定义?而尝试输出abc就能得到变量未定义的错误呢?

这是因为在JavaScript中使用var定义的变量会被预先提升到作用域最开始的地方(这里就是这个function), 在这个例子中也就是if位置的上面, 代码就可以写成:

function checkStatus(status) {
  var statusLabel;
  if (status) {
    statusLabel = 'ok';
    console.log(statusLabel);
  } else {
    console.log(statusLabel);
  }
}

这是JavaScript独有的, 所以之前定义变量的好的习惯就是在所有可能会使用的地方之前定义好,如此,才不会产生各种奇怪奇怪的问题。

  • Let

let就是新的 var,和var不同的是它是块级的,将上面的代码中的var换成let

function checkStatus(status) {
  if (status) {
    let statusLabel = 'ok';
    console.log(statusLabel);
  } else {
    console.log(statusLabel);
  }
}
checkStatus(true);
checkStatus(false);

这样的到的结果就是我们设想的,true的时候是ok, false的时候抛出变量不存在的错误,如果false的时候想要输出undefined, 那么就要手动定义在 if 的上面:

function checkStatus(status) {
  let statusLabel;
  if (status) {
    statusLabel = 'ok'
    console.log(statusLabel);
  } else {
    console.log(statusLabel);
  }
}
checkStatus(true);
checkStatus(false);
  • const

const 和 let 一样是块级, 从名字上看是用来常量的,其实不然,正确的说法是 single-assignment, 也就是说只能对其进行一次赋值并且只能在定义的时候赋值,后面如果再想对其进行赋值操作就会报错。

const PI = 3.1415926;
PI = 2.0; //报错,Uncaught TypeError: Assignment to constant variable.

但是,这不代表const定义的就不可以改变的(immutable), 如下代码:

const animals = ['rabbit', 'monkey'];
console.log(animals); //['rabbit', 'monkey']
animals.push('donkey');
console.log(animals);//['rabbit', 'monkey', 'donkey']
animals = ['bird']; //报错,Uncaught TypeError: Assignment to constant variable.

那如何决定该使用哪种关键词呢?

这个目前社区没有统一的规范,不过本人比较喜欢下面这种,即:

  • 优先使用let
  • 常量用const, 如常规常量, 导入的模块等等。
  • 全局变量使用var (基本上可以不用了😄)