點燈坊

失くすものさえない今が強くなるチャンスよ

ECMAScript 之 let

Sam Xiao's Avatar 2020-11-24

ECMAScript 2015 是 ECMAScript 歷史上最重要一次升級,也讓 ECMAScript 終於趕上主流程式語言高度,若要明顯的分辨 ES5 與 ES6,最明顯的方式的方式就是看有沒有使用 let

Verson

ECMAScript 2015

Let

宣告變數於 block {}內。

var 宣告變數於 function 內或 function 外 (global)

Scope

function f() {
  var x = 1

  if (true) {
    var x = 2
    console.log(x)
  }

  console.log(x)
}

f()

ES5 與 ES6 都可執行,但結果卻是兩個 2

var 因為 hoisting 在 creation phase 就已經定義 x,且 scope 為 function 內,因此離開 if (true) 仍然為 2

let000

function f() {
  let x = 1

  if (true) {
    let x = 2
    console.log(x)
  }

  console.log(x)
}

f()

改用 ES6 的 let,結果為 21

第 4 行

if (true) {
  let x = 2;
  console.log(x);
}

使用 let 後,其 scope 為 {} 而非 function,只有在 {}2,離開 {} 就變回 1

以主流程式語言而言,變數的 scope 都是 block {} 而非 function,因此 ECMAScript 的 let 較符合大家習慣,因此 TC39 建議全面使用 let 取代 var

let001

function f(cnt) {
  for (var i = 0; i < cnt; i++) {}
  console.log(i)
}

f(5)

var 為 function level,因此 for loop 執行完還存在。

let002

function f(cnt) {
  for (let i = 0; i < cnt; i++) {}
  console.log(i)
}

fn(5)

let 為 block level,超出 for loop 就抓不到了。

for loop 應全面使用 let 避免 side effect

let003

var x = 'global'
let y = 'global'

console.log(window.x)
console.log(window.y)

varlet 雖然都可建立 global 變數,但 var 會污染 DOM 的 window object,但 let 不會。

若要使用 global 變數,應全面使用 let 取代 var

let004

Redeclaration

var x = 2
console.log(x)

var x = 3
console.log(x)

ES5 與 ES6 都可以執行。

var 允許對 variable 重複宣告。

let005

let x = 2;
console.log(x);

let x = 3;
console.log(x);
// SyntaxError

ES5 與 ES6 都無法執行。

let 不允許對 variable 重複宣告。

let006

function fn(x) {
  switch(x) {
    case 0:
      var y = 2;
      console.log(y);
      break;
      
    case 1:
      var y = 3;
      console.log(y);
      break;
  }
}

fn(1);
// 3

ES5 與 ES6 都可執行。

因為 var 會 hoisting,所以允許 redeclaration。

let007

function fn(x) {
  switch(x) {
    case 0:
      let y = 2;
      console.log(y);
      break;
      
    case 1:
      let y = 3;
      console.log(y);
      break;
  }
}

fn(1);

若將 var 改成 let,則 ES5 與 ES6 都無法執行。

因為 let 認 {} 為 scope,不允許 redeclaration。

let008

function f(x) {
  switch(x) {
    case 0: {
      let y = 2
      console.log(y)
      break
    }
    case 1: {
      let y = 3
      console.log(y)
      break
    }
  }
}

f(1)

在每個 case 加上 {},則可以 redeclaration。

let009

Conclusion

  • var 為 function level 或 global level;而 let 為 block level
  • var 的 global 變數會污染 DOM 的 window object,但 let 不會
  • 實務上建議全面使用 let 取代 var

Reference

MDN JavaScript, let