前端开发让前端飞程序员

ES6之let与const

2018-12-28  本文已影响7人  前端王睿
思维导图

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

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

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


一、let——变量声明

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

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——常量声明

constlet很像,所以本文也是直接把他们放在一起说,它几乎与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一样适用,因此不再赘述。

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

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在同一作用域内不可重复声明同一变量,包括varconst声明过的也不行
const声明常量,不可更改,但如果是引用类型常量,则可以修改其内部数据
const具有let相同特性(包括①②③所有特性)
const在声明常量时必须同时进行赋值

上一篇下一篇

猜你喜欢

热点阅读