今天看啥  ›  专栏  ›  前端王睿

ES6之let与const

前端王睿  · 简书  ·  · 2018-12-28 21:23
思维导图

JavaScript共包含三个部分: ECMAScript、DOM和BOM ,而我们今天开始所要讲的ES6的全称就是ECMAScript6,它是2015年发布的ECMAScript标准,故又被称之为ECMAScript2015。而后每年都会更新一个新版本,并以该年份置于其后作为标识,而这些从2015年开始的ECMAScript版本都被统称为ES6。

ES6相对之前版本增加了很多新的特性,但是也有很多都只是 语法糖 ,也就是说实现功能和之前一样,只是语法更简洁了而已(如箭头函数、类)。这些新特性新语法给我们开发带来了很多便利,提高了工作效率和降低了维护成本。遗憾的是,现代浏览器对ES6兼容参差不齐,所以导致很多人虽然想用但是不敢用。不过幸亏有了像Babel这样优秀的编译工具,能将ES6语法编译成现代浏览器能识别的ES6之前版本,这样我们又可以轻松愉快地使用它了。

接下来,就让我来为大家一步步地打开这扇通往ES6的大门吧!


一、let——变量声明

在ES6之前,我们是使用 var 来声明变量,那么我们就来简单说说 var let 之间到底有什么区别。

1. 块级作用域

var 声明的变量不是块级作用域,所以代码块之外能访问代码块中的变量。

{   // 代码块
  var a = 0;  // 全局变量,外部可访问
}
console.log(a);   // 0

let 声明的变量是块级作用域,所以代码块之外无法访问代码块中的变量。

{   // 代码块
  let a = 0;  // 局部变量,外部可访问
}
console.log(a);   // 报错

2. 暂时性死区

var 声明的变量会进行变量提升,也就是说,该变量声明总会被提升到作用域最顶部。

{
  a = 0;
  var a;
}
console.log(a);   // 0

变量 a 的作用域为全局,故以上代码其实相当于下面代码:

var a;  // 变量提升
{
  a = 0;
}
console.log(a);   // 0

然后再看下面这个例子:

console.log(a);   // undefined
{
  a = 0;
  var a;
}

你会发现即使最上面没有声明过变量 a ,我们去打印它也并不会报错,这是因为 var a; 会提升到 console.log(a); 之前。

let 比较霸道,用它声明的变量必须在其作用域内并在声明之后使用,即使全局已经用 var 声明过该变量也不行。

{
  a = 0;   // 在声明前赋值会报错
  let a;
}
// 在声明前使用就会报错,不管代码块外面是否声明过这个变量
var a; 
{
  a = 0;  // 报错
  let a;
}

后面这个例子可以看到,虽然全局已经声明过了变量 a ,本来代码块中是可以正常访问到这个变量的,但因为这个代码块中用 let 又声明了一次变量 a ,因此这个代码块就像一片 “死区” 一样,无法访问外部变量,当然这只是针对这个用 let 声明的 a 来说是 “死区” ,若是用 var 声明的其他变量则照样可以访问外部变量。这种用 let 绑定整个代码块的“霸道行为”,在语法上被称之为 “暂时性死区”

其实,按照我个人理解,我们完全可以不用去理会这个 “暂时性死区” 的具体含义,只需知道的是,不管什么情况, let 声明的变量,必须在其声明之后才能使用

3. 不能重复声明

var 比较开放, 同一作用域内, 同一变量可以声明多次,并不会报错。

var a = 0;
var a = 1;
console.log(a);  // 1

以上代码相当于:

var a;
a = 0;
a = 1;
console.log(a);  // 1

let 比较专一, 同一作用域内, 同一变量只能声明一次,否则就会报错。

let a = 0;
let a = 1;  // 报错
let a = 0;
var a = 1;  // 变量提升,报错
var a = 1;
let a = 0;  // 报错
let a = 0;
{
  var a = 1;  // 变量提升,报错
}

但是注意以下情况是正常的:

let a = 0;
{
  let a = 1;  // 无变量提升,是局部变量,与全局声明的变量不在同一个作用域
}
console.log(a);  // 0
var a = 0;
{
  let a = 1;  // 无变量提升,是局部变量,与全局声明的变量不在同一个作用域
}
console.log(a);  // 0

其实只需记住一点: 在同一作用域中判断 ,这样就能很好地判断是否重复声明了。

二、const——常量声明

const let 很像,所以本文也是直接把他们放在一起说,它几乎与 let 一样,只不过它声明的是常量, 常量值不能更改 ,且必须 在声明时赋值

1. 声明常量

既然是常量,当然是不可更改的。

const a = 0;
a = 1;  // 报错,常量值不可更改

但是要注意下面这种情况是可以的:

const a = [];
a.push(1);
console.log(a)  // [1]

这是为什么呢?不是说常量值不可更改吗?可现在为什么又把空数组变成了 [1] 呢?

其实道理很简单,我们开始赋值给常量 a 的只是数组的引用而已(就是数组的存储地址),当我们去修改该数组时,这个引用并不会发生改变。 这就像是你给家里房子装修布置了一下,但是家庭地址并没有变,可是如果你直接换了一套新房,那可就不一样了。

const a = [];
a = [1];  // 报错,引用不可更改

这是重新赋值了新的数组,引用发生改变,所以就会报错。

2. 具有let相同特性

块级作用域 先声明后使用 不能重复声明 这些特性对于 const 一样适用,因此不再赘述。

但需要注意的是,用 var let 声明过的变量,再声明相同名称常量也算是重复声明。

var a;
const a = 0;   // 报错
let a;
const a = 0;   // 报错
const a = 0;
var a;   // 报错
const a = 0;
let a;   // 报错

3. 声明时必须赋值

const a;   // 报错

let 声明的是变量,所以可以先声明后赋值,可 const 不一样,它声明的时常量,你在声明的同时就必须给其赋值,否则它不会给你好心地默认给你赋个 undefined ,而是毫不留情地给你报错!


重点总结

let 在代码块中声明的变量为局部变量
let 声明的变量,必须在其声明之后才能使用
let 在同一作用域内不可重复声明同一变量,包括 var const 声明过的也不行
const 声明常量,不可更改,但如果是引用类型常量,则可以修改其内部数据
const 具有 let 相同特性(包括①②③所有特性)
const 在声明常量时必须同时进行赋值




原文地址:访问原文地址
快照地址: 访问文章快照