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。

相關文章
相關標籤/搜索