iT邦幫忙

2021 iThome 鐵人賽

DAY 11
1

這兩天會介紹到 JS 內 var 與 let 的差異,今天跟明天分別介紹兩點。

JS 的 var 以及 let 主要在以下四點有差異:

  1. 作用範圍 Scope
  2. 變數提升 Hoisting
  3. 執行環境 Execution Context
  4. 宣告 declaration

作用範圍 Scope:

在區域內的作用範圍不同。

  • var : 以 function( ) 為作用範圍
  • let : 以 block { } 為作用範圍

簡單來說,function 可以關住 var 及 let (因為 function 也有使用到 { } ),而 block 只能關住 let。

當 var 的作用範圍在 block { } 時,var 無法被關住,會溢出到外面變成全域變數,JS 會自動在全域環境下宣告一個 i 變數出來。

範例

for (var i = 0; i < 3; i++) {
    console.log(i)             
//  印出 0, 1, 2
}

console.log(i)                 
//  印出 3
//  因為 { } 無法關住 var ,造成 i 溢出。
//  在上個迴圈的 i 遞增到3就停止了,JS 會在全域環境下生出 var i = 3。
//  導致最後外層的 console.log 印出3
                               
for (let j = 0; j < 3; j++) {
    console.log(j)             
//  印出 0, 1, 2
}

console.log(j)                 
//  印出 "error" ReferenceError: j is not defined
//  因為 let 被 { } 關住,所以 j 不會溢出。
//  外層沒有 j 變數,導致噴錯。

變數提升 Hoisting:

JS裡才特有的東西,若用 var 將變數定義在函式下方,執行結果不會跑出 not define,而是跑出undefined,是因為 JS 把變數提升移動到函式上方(大眾說法),但其實裡面的程式碼並不會上下跑動。

JS執行程式時會經歷兩段時期:

  1. 建立期:JS 會先分配記憶體給宣告的變數及函式,其中函式又會比變數優先被宣告。

    在建立期會做兩件事情(依照 1A、1B 的順序):
    1A:註冊名稱 = 建立罐子,JS 會宣告變數,但不會賦值給變數。
    1B:初始化 = 給他空氣,因為沒有值的關係,這個變數的值會是 undefined。

  2. 執行期:執行程式碼。

    在執行期也會做兩件事情(依照程式碼由上至下的順序):
    2A:把宣告變數裡的值指定給變數。
    2B:執行函式。

  • var 有變數提升,在 1B 初始化的時期,變數會被賦予 undefined,即使把宣告寫在後面也能執行,不會出錯。
  • let 有變數提升,但是 let 要等到 2A 賦值之後,才能進行 1B 的初始化,在那之前會被 TDZ 蓋住,導致 JS 無法讀取他,最後會出錯。

var

console.log(a)
var a = 1
//  印出 undefined

//  程式碼由上開始往下讀取
//  1.跳過 console.log
//  2.執行 1A  var a
//  3.執行 1B  var a = undefined
//  4.回到 console.log ,執行 2B  undefined => 被印出
//  5.執行 2A  a = 1

let

  • 用 var 在宣告時,變數會變成全域變數。
  • 用 let 宣告時,變數會變成區域變數,JS 在 1A 時會用一個 TDZ (Temporal Dead Zone 暫時死區) 把變數蓋住,當給予值後才能把蓋子打開。
console.log(a)
let a = 1
//  印出 Cannot access 'a' before initialization

//  程式碼由上開始往下讀取
//  1.跳過 console.log
//  2.執行 1A  let a 並且給他一個TDZ
//  3.執行 1B  變數a因為被 TDZ 蓋住,所以無法執行初始化
//  4.回到 console.log 執行 2B ,因為a被蓋住無法進行 1B 的初始化
//  ReferenceError: Cannot access 'a' before initialization => 被印出

參考:
[1]What's the difference between using "let" and "var"?


上一篇
Day 10 JavaScript CSS in JS
下一篇
Day 12 JavaScript var vs let (2)
系列文
網頁前後端寶石庫-礦坑補完計畫30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言