ES6 系列一:let和const

"Code tailor",为前端开发者提供技术相关资讯以及系列基础文章,微信关注“小和山的菜鸟们”公众号,及时获取最新文章。

前言

在开始学习以前,咱们想要告诉您的是,本文章是对阮一峰《ECMAScript6 入门》一书中 "let 和 const 命令" 章节的总结,若是您已掌握下面知识事项,则可跳过此环节直接进入题目练习javascript

  • 出现起因
  • 什么是暂时性死区?
  • 什么是变量提高?
  • 是什么块级做用域?

若是您对某些部分有些遗忘,👇🏻 已经为您准备好了!前端

学习连接

let 和 const 的学习java

汇总总结

出现起因

在 ES5 中,只有全局做用域函数做用域,没有块级做用域,这带来了不少不合理的场景,好比:内层变量可能覆盖外层变量、用来计数的循环变量泄露为全局变量。因此,let 和 const 实际上引入了“块级做用域”的概念es6

变量提高

var 命令会发生”变量提高“的的现象,即变量可在声明以前使用,而通常逻辑是先声明变量再去使用变量。故为了纠正此现象,let 命令改变了语法行为,即它所声明的变量必定要在声明后使用。
// var 的状况
console.log(foo) // 输出undefined
var foo = 2

// let 的状况
console.log(bar) // 报错ReferenceError
let bar = 2

块级做用域

块级做用域可经过新增命令 let 和 const 声明,所声明的变量在指定块的做用域外没法被访问。块级做用域在以下状况被建立:微信

  • 在一个函数内部
  • 在一个代码块(由一对花括号包裹)内部
  • 外层代码块不受内层代码块的影响
function f1() {
  let n = 5
  if (true) {
    let n = 10
  }
  console.log(n) // 5
}

let 命令

  • 只在代码块中生效
{
  let a = 10
  console.log(a) //10
}
console.log(a) //undefined
  • 无变量提高
console.log(bar) // 报错ReferenceError
let bar = 2
  • 不可重复声明
//报错
let a = 10
let a = 20

const 命令

  • 只读常量,一旦声明,就不能改变,且必须初始化
  • 做用域与 let 相同
  • 无变量提高
  • 存在暂时性死区
  • 不可重复声明
const MAX = 1000000
const MIN //SyntaxError
const MAX = 10000 //报错

暂时性死区

在代码块内,使用 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命令声明变量tmp以前,都属于变量tmp的“死区”。

题目自测

一: 下面的代码输出什么?函数

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1)
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1)
}
  • A: 0 1 2 and 0 1 2
  • B: 0 1 2 and 3 3 3
  • C: 3 3 3 and 0 1 2

Answer:C学习

因为 JavaScript 中存在事件队列,所以在执行循环以后会调用setTimeout回调函数。由于第一个循环中的变量 i 是使用var关键字声明的,因此这个值是全局的。在循环过程当中,咱们使用一元运算符++将 i 的值每次递增 1。在调用setTimeout回调函数时,在第一个示例中 i 等于 3。在第二个循环中,变量 i 是使用 let 关键字声明的:使用let(and const)关键字声明的变量是块范围的(块是介于{}之间的任何东西)。在每次迭代中,都会有一个新值,每一个值的做用域都是独立的。code


二: 下面代码输出什么?队列

function sayHi() {
  console.log(name)
  console.log(age)
  var name = 'Lydia'
  let age = 21
}

sayHi()
  • A: Lydia and undefined
  • B: Lydia and ReferenceError
  • C: ReferenceError and 21
  • D: undefined and ReferenceError

Answer:D事件

在函数中,咱们首先用 var 关键字声明 name 变量。这意味着变量将被提高(内存空间在建立阶段设置),默认值为 undefined,直到咱们实际到达定义变量的行。咱们尚未在试图记录 name 变量的行中定义变量,因此它仍然保存 undefined 的值。

带有 let 关键字(和 const)的变量会被提高,但与 var 不一样的是,不会被初始化。在咱们声明(初始化)它们以前,它们是不可访问的。这就是所谓的“暂时死区”。当咱们试图在声明变量以前访问它们时,JavaScript 抛出一个 ReferenceError。


三: 下面代码输出什么?

let name = 'Lydia'

function getName() {
  console.log(name)
  let name = 'Sarah'
}

getName()
  • A: Lydia
  • B: Sarah
  • C: undefined
  • D: ReferenceError

Answer:D

每一个函数都有本身的执行上下文(或做用域)。getName 函数首先在它本身的上下文(做用域)中查看它是否包含咱们试图访问的变量名。在本例中,getName 函数包含它本身的 name 变量:咱们用 let 关键字和'Sarah'值声明变量名。

带有 let 关键字(和 const)的变量会被提高,但与 var 不一样的是,不会被初始化。在咱们声明(初始化)它们以前,它们是不可访问的。这就是所谓的“暂时死区”。当咱们试图在声明变量以前访问它们时,JavaScript 抛出一个 ReferenceError。

若是咱们没有在 getName 函数中声明 name 变量,javascript 引擎就会向下查看做用域链。外部做用域有一个名为 name 的变量,其值为 Lydia。若是那样的话,它会记录为 Lydia。

相关文章
相关标签/搜索