整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
淺談 var 與 let 的差異以及有無宣告變數的差異
前言
在網路上其實滿多人都有講過 var 與 let 的差異以及有無宣告變數的差異,所以我這邊也來談一下這兩個最大的差異以及有無宣告變數的差異。
有無宣告變數的差異
其實應該打「有無使用 var 的差異」才對,但是中文來講確實是宣告變數的差異,在說明這個差異之前,必須先瞭解到幾個東西
- 全域環境
- 全域物件
但是上面這兩個觀念在我先前的「[JS奇怪的世界]No.3 全域環境與全域物件」有介紹過,所以這邊就不多做介紹,所以這邊就直接來講重點。
在一般狀況下使用 var 與沒有使用 var 最大差別在於「可不可以被 delete 刪除」。
首先 delete 是一個刪除物件屬性的語法,在 MDN 這邊有介紹,因此我們可以透過以下語法了解有無宣告 var 的差異
1 | |
透過上面我們可以了解到一件事情,如果沒有使用 var 宣告的變數「會被當作物件屬性新增」的方式新增,因此就會強烈建議你變數一定要使用 var 宣告,否則可以被刪除的變數是很容易出現系統上的 bug。
這邊我們先不講 let、const。
作用域
接下來先讓我們了解一下 var 與 let、const 的作用域,通常來講我們都會建議使用者可以將過去用 var 宣告的變數通通改成 let,但 let 與 var 差異在哪裡?
先來講講 var 的作用域,var 的作用域是「函式作用域」,函式作用域的意思是說,它是依照函式來決定自己的變數作用域,舉例來講
1 | |
我們無法直接取得宣告在 fuA 中的變數,儘管它已經呼叫並執行。
那 let 呢?let 的作用域是「區塊作用域」,最簡單的辨別的方式就是只要有「{ }」花括號就是它的作用域範圍
1 | |
如果這邊的範例你是拿函式當作比較那麼就會看不出所以然,因為作用域雷同。
1 | |
但若是使用 if 這類就會可以看出差異
1 | |
所以使用 let 宣告變數的好處在於,我們可以確保不會污染到全域物件,因為只要不是在「函式內宣告」的變數,都會污染到全域物件,例如上述的 if 範例就會污染的全域物件

那你可以會問:「const呢?」,其實與 let 相同。
在這邊就不提 Hoisting 了,下一次有機會再來講。
為什麼 let 無法從 window 中找到
在這邊這是一個很少很少有人提到的一件事情,首先在以往當我們輸入以下變數宣告後都可以在 window 下找到相關變數
1 | |

但是當我們使用了 ES6 語法,也就是 let 或是 const 卻無法找到這個變數
1 | |

但這邊我們若使用 aName 卻又可以正確取得已經宣告的變數

那麼這是什麼神奇的原因?在以往我們的觀念中,通常我們宣告的變數都會被加入到 window 中,但使用 let 宣告的變數卻無法在 window 底下找到,可以卻又可以正確的呼叫取得該變數的值,當你嘗試使用 delete aName,你也會得到一個 false 無法刪除的警告。
那這是魔術嗎?其實不是。
這個原因是出在全域執行環境(Global space) 上面,首先這個全域執行環境其實是由兩個環境所組成的
- 全域物件 - Object Env
- 宣告環境 - Declare Env
因此全域執行環境(Global space) 其實是一個由雙環境組成的東西,一般來說我們是看不到 Declare Env 的。
所以 var 其實是基於 ObjectEnv 宣告並加入到 Declare Env,而 let、const 則是只會宣告在 Declare Env 中,這也就是為什麼我們無法在 Window 上面看到由 let、const 宣告的變數但卻又可以正常取得到值的原因。
參考文獻
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ