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

相關文章
相關標籤/搜索