let 和 const 命令詳解

1、let 命令

    ES6新增了let,用來聲明變量,它的用法類似於 var,但是所聲明的變量,只在let命令所在的代碼塊內有效。

   

{
  let a = 1
  var b = 2
}

console.log(a) // ReferenceError: a is not defined.
console.log(b) // 2

下面講述下 let 相對於 var 的特性

變量提升和暫時性死區

 先來看一個例子

// var 的情況
console.log(a); // 輸出undefined
var a = 2;

// let 的情況
{
    console.log(b); // 報錯ReferenceError
    let b = 2;
}

  上面的代碼中 var 聲明的變量發生了變量提升,即腳本開始運行時,變量a已經存在了,但是沒有值,所以會輸出undefined。注意一個細節,變量聲明分爲兩部分,創建和初始化

var 聲明的時候,創建跟初始化過程都提升了,但是let 只有創建的時候發生了提升,初始化並沒有提升,下面看下過程.

var 的情況

  1. 找到所有用 var 聲明的變量,在環境中「創建」這些變量
  2. 將這些變量「初始化」爲 undefined。
  3. 開始執行代碼
  4. a = 2 將 a 變量「賦值」爲 1

也就是說 var 聲明會在代碼執行之前就將「創建變量,並將其初始化爲 undefined」。

這就解釋了爲什麼在 var a =  2 之前 console.log(a) 會得到 undefined。

let 的情況

  1. 找到所有用 let 聲明的變量,在環境中「創建」這些變量
  2. 開始執行代碼(注意現在還沒有初始化)
  3. 執行 b = 2,將b 「初始化」爲 2(這並不是一次賦值,如果代碼是 let b,就將 b 初始化爲 undefined)

發現什麼區別沒有,let在執行代碼之前並沒有對變量進行初始化。也就是說let聲明變量,只有創建過程發生了提升。

ES6 明確規定,如果區塊中存在letconst命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。

所謂暫時死區,就是不能在初始化之前,使用變量。 

 

塊級作用域

 ES5 只有全局作用域和函數作用域,沒有塊級作用域,這帶來很多不合理的場景。例如:

// 第一種
var str = 'outside'

function f() {
  console.log(tmp);
  if (true) {
    var str = 'indside';
  }
}

f(); // undefined
// 第二種
var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

上面代碼,函數f執行後,輸出結果爲undefined,原因在於變量提升,導致內層的 str 變量覆蓋了外層的tmp變量。第二種for循環,用來計數的循環變量泄露爲全局變量。如果用let來寫循環,例如:

for (let i = 0; i < 5; i++) {
    let i = 'Tom'
    console.log(i) // 輸出Tom 5 次
}
console.log(i) // i is not defined

 上面的循環就充分的體現了let 的塊級作用域特性,for循環的條件判斷是一個隱藏的塊級,循環主題是另外一個塊級,所以可以有兩個變量i,互不干擾,同時循環變量在循環結束後就被回收了。

 

不允許重複聲明

let 不允許在相同作用域內,重複聲明同一個變量。

function aa () {
    var a = 11
    var a = 22
}
aa() // 不報錯

function bb () {
    var a = 11
    let a = 22
}
bb() // 報錯

function cc () {
    let a = 11
    let a = 22
}
cc() // 報錯

function dd () {
    let a = 11
    {
        let a = 22
    }
}
dd() // 不報錯

2、const命令

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

const PI = 3.1415;

console.log(PI) // 3.1415

PI = 3 // TypeError

const一旦聲明變量,就必須立即初始化,不能留到以後賦值。

const a;
// SyntaxError: Missing initializer in const declaration

 

const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。如果聲明的數據類型是引用型,是可以改變的

const arr = []

arr.push('a') // 可以執行

arr = 2 // 報錯

const命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置後面使用。

{
    console.log(A) // ReferenceError
    const A = 5
}

 

 

到這裏差不多講的都差不多了,let 跟 const 是 es6 新增的兩種聲明變量的命令,還有其他幾種聲明命令分別是 var ,function ,import ,class 。有興趣的小夥伴可以去了解下~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章