ES6语法之 let 和 const

以往,在 JavaScript 中声明变量的惟一方式是使用关键字 var。为了理解为什么添加了 letconst,咱们先看一个示例,了解使用 var 会带来怎样的麻烦。数组

var 变量提高

下面代码中你认为运行 getClothing(false) 后的输出是什么?浏览器

function getClothing(isCold) {
 if (isCold) {
   var freezing = 'Grab a jacket!';
 } else {
   var hot = 'It's a shorts kind of day.';
   console.log(freezing);
 }
}

答案是输出undifind, 本质上,在执行任何 JavaScript 代码以前,全部变量都会被“提高”,也就是提高到函数做用域的顶部。所以在运行时,getClothing() 函数实际上看起来以下所示…数据结构

function getClothing(isCold) {
  var freezing, hot;
 if (isCold) {
   freezing = 'Grab a jacket!';
 } else {
   hot = 'It's a shorts kind of day.';
   console.log(freezing);
 }
}

let 和 const

使用 letconst 声明的变量解决了这种提高问题,由于它们的做用域是到块,而不是函数。以前,当你使用 var 时,变量要么为全局做用域,要么为本地做用域,也就是整个函数做用域。 函数

若是在代码块(用花括号 { } 表示)中使用 letconst 声明变量,那么该变量会陷入暂时性死区(temporal dead zone),直到该变量的声明被处理。这种行为会阻止变量被访问,除非它们被声明了。this

下面例子中, 你认为运行 getClothing(false) 后的输出是什么?指针

function getClothing(isCold) {
  if (isCold) {
    const freezing = 'Grab a jacket!';
  } else {
    const hot = 'It's a shorts kind of day.';
    console.log(freezing);
  }
}

答案是 ReferenceError: freezing is not defined.code

关于使用 let 和 const 的规则

let 和 const 还有一些其余有趣特性。
  • 使用 let 声明的变量能够从新赋值,可是不能在同一做用域内从新声明。
  • 使用 const 声明的变量必须赋初始值,可是不能在同一做用域内从新声明,也没法从新赋值。
let instructor = 'James';
instructor = 'Richard';
console.log(instructor); //Richard
const instructor = 'James';
instructor = 'Richard';
console.log(instructor); //SyntaxError: Identifier 'instructor' has already been declared

使用案例

最大的问题是什么时候应该使用 letconst?通常法则以下:对象

  • 当你打算为变量从新赋值时,使用 let
  • 当你不打算为变量从新赋值时,使用 const

由于 const 是声明变量最严格的方式,咱们建议始终使用 const 声明变量,由于这样代码更容易读懂,你知道标识符在程序的整个生命周期内都不会改变。若是你发现你须要更新变量或更改变量,则回去将其从 const 切换成 let生命周期

const实际上保证的,并非变量的值不得改动,而是变量指向的那个内存地址不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,所以等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于它指向的数据结构是否是可变的,就彻底不能控制了。所以,将一个对象声明为常量必须很是当心。ip

const foo = {};

// 为 foo 添加一个属性,能够成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另外一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另外一个地址,但对象自己是可变的,因此依然能够为其添加新属性。

顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。

从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

var a = 1;
// 若是在 Node 的 REPL 环境,能够写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1

let b = 1;
window.b // undefined

上面代码中,全局变量avar命令声明,因此它是顶层对象的属性;全局变量blet命令声明,因此它不是顶层对象的属性,返回undefined

var 该怎么办?

还有必要使用 var 吗?没有了。

在某些状况下有必要使用 var,例如若是你想全局定义变量,可是这种作法一般都不合理,应该避免。从如今开始,建议放弃使用 var,改成使用 letconst

相关文章
相关标签/搜索