# JavaScript - VAR vs LET vs CONST

## :mag: 以 "宣告與賦值" 來看:
- **var** 為宣告"變數"
- 宣告同時可以不賦予值,預設值為undefined
- 賦予值之後,可以重新賦予新值
- 可以重複地宣告同一個變數,宣告(將被提升的部分)會被忽略,但賦值不會
- **let** 為宣告"變數"
- 宣告同時可以不賦予值,預設值為undefined
- 賦予值之後,可以重新賦予新值
- 只能在同一個作用域內宣告一次
- **const** 則是宣告"常數",*constant* 的縮寫
- 宣告同時必須賦予值
- 賦予值之後,無法重新賦予常數新值(無法改變常數的值)
- 只能在同一個作用域內宣告一次
### 宣告時不賦予值
:dart: **var**
```javascript=
var aVar;
console.log('aVar = ' + aVar); // aVar = undefined
```
:dart: **let**
```javascript=
let aLet;
console.log('aLet = ' + aLet); // aLet = undefined
```
:dart: **const**
```javascript=
const aConst;
console.log('aConst = ' + aConst); // SyntaxError: Missing initializer in const declaration
```
### 賦予值之後,重新賦予新值
```javascript=
var aVar = 'a';
console.log('aVar = ' + aVar); // aVar = a
aVar = 'b';
console.log('aVar = ' + aVar); // aVar = b
let aLet = 'a';
console.log('aLet = ' + aLet); // aLet = a
aLet = 'b';
console.log('aLet = ' + aLet); // aLet = b
const aConst = 'a';
console.log('aConst = ' + aConst); // aConst = a
aConst = 'b';
console.log('aConst = ' + aConst); // TypeError: Assignment to constant variable
```
### 重複宣告
:dart: **var**
```javascript=
var aVar = 'a';
var aVar = 'b';
var avar;
console.log('aVar = ' + aVar); // aVar = b
```
:dart: **let**
```javascript=
let aLet = 'a';
let aLet = 'b'; // SyntaxError: Identifier 'aLet' has already been declared
console.log('aLet = ' + aLet);
```
:dart: **const**
```javascript=
const aConst = 'a';
const aConst = 'b'; // SyntaxError: Identifier 'aConst' has already been declared
console.log('aConst = ' + aConst);
```
## :mag: 以"作用域"來看:
- var 為 function scope
- 以"函式"來分割變數的作用域
- let、const 為 block scope
- 以"區塊"來分割 變數/常數 的作用域( { } or ( ) )
- ex. function、for、if、switch、while、try / catch
### :dart: var - Function Scope
```javascript=
function test(){
var aVar = 'a';
console.log('aVar = ' + aVar); // aVar = a
}
test();
console.log('aVar = ' + aVar); // ReferenceError: aVar is not defined
```
### :dart: let、const - Block Scope
```javascript=
for (let aLet = 0; aLet < 3; aLet++) {
console.log('aLet = ' + aLet); // aLet = 0 、 aLet = 1 、 aLet = 2
}
console.log('aLet = ' + aLet); // ReferenceError: aLet is not defined
```
```javascript=
{
const aConst = 'c';
console.log('aConst = ' + aConst); // aConst = c
}
console.log('aConst = ' + aConst); // ReferenceError: aConst is not defined
```
## :mag: 以 " [Hoisting]() " 來看:
- var
- **宣告**的部分**會被提升**
- 提升後會先被**初始化**為 undefined
- let、const
- **宣告**的部分**會被提升**
- 被提升後則**不會**先被**初始化**
- 在宣告前對其做存取,會產生[**暫時性死區**]()的問題
:::success
:bulb: var、let、const 都會被提升,差別在於**提升時初始化與否**
:::
:dart: **var**
```javascript=
console.log('aVar = ' + aVar); // aVar = undefined
var aVar = 'a';
console.log('aVar = ' + aVar); // aVar = a
```
:dart: **let**
```javascript=
console.log('aLet = ' + aLet); // ReferenceError: Cannot access 'aLet' before initialization
let aLet = 'b';
```
:dart: **const**
```javascript=
console.log('aConst = ' + aConst); // ReferenceError: Cannot access 'aConst' before initialization
const aConst = 'c';
```
## :mag: 以"存入全域物件"來看
在 Global Scope 中**賦值**,將被存入 **window** 這個**全域物件**中
```javascript=
//Golbal Scope
world = 'Hello!!!'
console.log(window.world); //Hello!!!
```
### 若在 Global Scope 中宣告 變數/常數 並賦予值:
- var
- 會 存入 **window** 中
- let 、 const
- 不會 存入 **window** 中
:dart: **var**
```javascript=
//Golbal Scope
var aVar = 'aVar';
console.log('window.aVar = ' + window.aVar); // window.aVar = aVar
```
:dart: **let**
```javascript=
//Golbal Scope
let aLet = 'aLet';
console.log('window.aLet = ' + window.aLet); // window.aLet = undefined
```
:dart: **const**
```javascript=
//Golbal Scope
const aConst = 'aConst';
console.log('window.aConst = ' + window.aConst); // window.aConst = undefined
```
<br><br><br><br><br>
參考如下:
> [[day21] YDKJS (Scope) : Hoisting ? let 會 Hoist 嗎 ? - 更進一步解釋 let hosting](https://ithelp.ithome.com.tw/articles/10225604#:~:text=%E7%B5%90%E6%9E%9C%E7%A8%B1%E4%BD%9CReferenceError%20.-,%E6%9B%B4%E9%80%B2%E4%B8%80%E6%AD%A5%E8%A7%A3%E9%87%8B%20let%20hosting,-%E9%80%99%E6%99%82%E5%80%99%EF%BC%8C%E9%9D%88%E9%AD%82%E7%9A%84)
> [[JavaScript] Javascript 中的 Hoisting(提升):幫你留位子 - let, const and Hoisting](https://medium.com/itsems-frontend/javascript-hoisting-589488622dd7#:~:text=%E6%8F%90%E5%8D%87%E8%87%B3%E5%A4%96%E9%9D%A2%E3%80%82-,let%2C%20const%20and%20Hoisting,-%E5%9C%A8%20W3C%20%E4%B8%AD)
> [W3School - JavaScript Hoisting](https://www.w3schools.com/js/js_hoisting.asp)
> [VAR vs LET vs CONST](https://pbs.twimg.com/media/EeVw-DOXgAAMtKk?format=jpg&name=900x900)
###### tags: `JavaScript`