ES6系列--全面瞭解let和const

前言

let 和 const 是 ES6 中新增的命令,是用於解決 ES5 中使用 var 命令聲明變量的一些問題而出現的, 在瞭解 let 和 const 以前,咱們先來簡單回看一下 var 命令的一些不合理的問題,而後再來 瞭解 let 和 const 的特性。javascript

var 的問題

var 主要有以下幾個不合理的地方:java

  • 沒有塊級做用域
  • 重複聲明
  • 綁定全局做用域
  • 變量提高

問題:沒有塊級做用域

ES5 只有全局做用域和函數做用域,沒有塊級做用域。git

for(var i = 0; i<10; i++){
    //... 
}
console.log(i); // 輸出 10
複製代碼

對於有塊級做用域的語言來講,for 語句初始化變量的表達式所定義的變量,只會存在於循環的環境中。 而對於 ES5 中的 var 命令來講,由 for 語句建立的變量 i 即便在 for 循環結束執行後,也依舊存在於循環外部的執行環境中。github

問題:重複聲明

使用 var 語句重複聲明變量是合法且無害的。安全

var a = 1;
console.log(a); //print : 1
var a = 2;
console.log(a); //print : 2
var a = 3;
console.log(a); //print : 3
複製代碼

在大多數語言中,在同一個做用域屢次聲明同一個變量是非法的,可是在 ES5 中使用 var 命令重複聲明的沒有任何問題的。數據結構

問題:綁定全局做用域

在全局做用域下經過 var 命令聲明變量,會建立一個新的全局變量做爲全局對象的屬性。函數

var a = 1;
console.log(window.a); // print: 1
複製代碼

咱們僅僅只是在全局做用域中經過 var 聲明瞭一個變量,這個變量竟然就掛載到了全局對象上, 這徹底超出了咱們的預期,是否是很不合理呢!ui

問題:變量提高

JS引擎在對代碼進行編譯解釋的時候,會查找全部經過 var 命令聲明的變量,會將建立變量的時機提高到當前做用域spa

第一個例子:指針

if( flg ){
    var value = 1;
}
console.log(value);
複製代碼

初學者可能會以爲只有 flg 爲 true 的時候,纔會建立 value,若是 flg 爲 false,結果應該是報錯,然而由於變量提高的緣由,代碼至關於:

var value;
if (flg) {
    value = 1;
}
console.log(value); // flg 爲true 的時候,輸出 1;flg 爲false 的時候,輸出 undefined
複製代碼

第二個例子:

console.log(tmp); // print : undefined
var tmp = 1;
console.log(tmp); // print : 1
複製代碼

初學者可能認爲咱們第一次打印 tmp 的時候應該拋出異常,由於此時 tmp 尚未聲明。 其實否則,由於 ES5 中的 var 命令存在變量提高,會將變量建立和初始化階段提高至做用域頂部, 將變量的賦值階段保留在當前位置。

let 和 const

爲了解決 var 所產生的種種不合理的狀況,ES6 新增了 let 和 const 命令,用於建立安全穩定易理解的變量。

改進:塊級做用域

ES6 中新增了塊級做用域,而且塊級做用域能夠任意嵌套

{
    let a = 1;
    console.log(a); // print: 1
}
console.log(a); // print error:ReferenceError: a is not defined
複製代碼

這個例子中,經過 let 命令聲明的變量 a 僅在塊級做用域內生效,因此在塊級做用域外引用變量 a 會提示未定義。

改進:不綁定全局做用域

let a = 1;
const b = 1;
console.log(window.a); // print: undefined
console.log(window.b); // print: undefined
複製代碼

let 和 const 命令在全局做用域下建立變量,並不會綁定至全局對象中。

改進:不存在變量提高

爲了糾正 var 命令會發生變量提高的現象,let 和 const 命令改變了語法行爲, let 和 const 所聲明的變量必定要在聲明後使用,不然報錯。

// var 的狀況
console.log(foo); // 輸出undefined
var foo = 2;

// let 的狀況
console.log(bar); // 報錯ReferenceError
let bar = 2;
複製代碼

上面代碼中,變量 foo 用 var 命令聲明,會發生變量提高,即腳本開始運行時,變量 foo 已經存在了,可是沒有值,因此會輸出 undefined。 變量 bar 用 let 命令聲明,不會發生變量提高。這表示在聲明它以前,變量 bar 是不存在的,這時若是用到它,就會拋出一個錯誤。

改進:不可重複聲明

let 和 const 不容許在相同做用域內,重複聲明同一個變量。

let a = 1;
var a = 2; //print error : Identifier 'a' has already been declared
複製代碼
let a = 1;
let a = 2; // print error: Identifier 'a' has already been declared
複製代碼

在函數體中從新聲明形參,一樣報錯

function fn(params){
    let params = 1;
} // print error: Identifier 'params' has already been declared
複製代碼

改進:暫時性死區

暫時性死區(Temporal Dead Zone),簡寫爲 TDZ。

let 和 const 聲明的變量不會被提高到做用域頂部,若是在聲明以前訪問這些變量,會致使報錯。

console.log(x); // print error: ReferenceError: value is not defined
let x = 1;
複製代碼

這是由於 JavaScript 引擎在掃描代碼發現變量聲明時,要麼將它們提高到做用域頂部(遇到 var 聲明), 要麼將聲明放在 TDZ 中(遇到 let 和 const 聲明)。 訪問 TDZ 中的變量會觸發運行時錯誤。 只有執行過變量聲明語句後,變量纔會從 TDZ 中移出,而後方可訪問。

簡單的來講,只要當前做用域內使用 let 和 const 命令建立了變量,那麼在當前做用域的開始直到變量聲明的一刻, 這個階段就叫作暫時性死區,也就是說從當前做用域的開始到變量建立的一刻,只要使用了這個變量就會報錯。

沒法使用和當前做用域內同名的外部變量

let name = 'tom';
function fn(){
    console.log(name); // print error : ReferenceError: name is not defined
    let name = 'jack'
}
fn();
複製代碼

typeof再也不是一個百分之百安全的操做

typeof x; // ReferenceError
let x;
複製代碼

變量 x 使用 let 命令聲明,因此在聲明前,都屬於 x 的死區,只要用到變量 x 就會報錯。

let 和 const 的區別

const 聲明的是一個只讀常量,一旦聲明,常量的值就不能改變。

const x = 1; 
x = 2; // print error: TypeError: Assignment to constant variable.
複製代碼

const 聲明的時候必須當即初始化,不能等到之後賦值,只聲明不賦值,就會報錯。

const y; // print error:SyntaxError: Missing initializer in const declaration
複製代碼

const 實際上保證的並非變量的值不可改動,而是變量指向的內存地址所保存的數據不可變動。

對於簡單類型,值就保存在變量指向的那個內存地址,所以等同於常量。

但對於引用類型的數據,變量指向的內存地址,保存的只是一個指向實際數據的指針, const 只能保證這個指針是固定的(即老是指向另外一個固定的地址), 至於它指向的數據結構是否是可變的,就徹底不能控制了

const foo = {};
foo.prop = 123;
foo.prop // 123

foo = {}; // print error: TypeError: Assignment to constant variable. 
複製代碼

上面代碼中,常量foo儲存的是一個地址,這個地址指向一個對象。 不可變的只是這個地址,即不能把foo指向另外一個地址,但對象自己是可變的,因此依然能夠爲其添加新屬性。

參考


預計每週1-2篇文章,持續更新,歡迎各位同窗點贊+關注

後續內容參見寫做計劃

寫做不易,若是以爲稍有收穫,歡迎~點贊~關注~

本文同步首發與github,歡迎在issues與我互動,歡迎Watch & Star ★

相關文章
相關標籤/搜索