---
# System prepended metadata

title: let、const、var的區别
tags: [javascript]

---

# let、const、var的區别
###### tags:`javascript`
不要用var，如果該變數會變，就用let，不變就用const。
### var
* 變數宣告
* 宣告時沒指定初始值也不會抱錯
* 可以重複宣告改值
* 容易被覆蓋
* 函式作用域(function scope):只能以函式為變數作用域的分界，在一些使用了區塊語句(用花括號的語句)的像if, else, for, while等等區塊語句中，會讓變數曝露到全域之中可被存取
* 變數提升:會替即將宣告的變數保留記憶體位置，若未宣告該變數，==會回傳undefind==
* 用var宣告全域變數，會成為window的屬性，但let和const不會。
```javascript=
var star="**"
var arr=3
var star="***"//可以重複宣告改值
```

---
### let
* 變數宣告，用在for迴圈
* let 在宣告的時候可以不用給值，若無初始值預設會給undefine
* 不允許重複宣告
* ==區塊作用域(block scope)== :以區塊語句為分界的作用域，它會比較明確而且不易發生錯誤。
* 變數提升:==宣告前不允許使用(暫時性死區)== 不讓開發者在「提升之後」到「賦值之前」的這段期間提取變數。==若未宣告該變數，會回傳錯誤==
```javascript=
let star="**"
let arr=3
let star="***"//Uncaught SyntaxError: Identifier 'fruit' has already been declared翻譯:let的"變數"不能定義兩次
```


---

### const數字(常數)
* 常數宣告，用在function解構=賦值
* ==⼀開始宣告時⼀定要給初始值==
* ==不允許重複宣告給值==但==物件跟陣列跟函式==的宣告，因為裡⾯記錄的是「地址」，類似於某⼤樓的地址，如果改變裡⾯的成員並不會更動到地址，所以==可以改變裡面的值==，所以對於物件、陣列、函式來說，使用const常數來宣告
* 區塊作用域(block scope):以區塊語句為分界的作用域，它會比較明確而且不易發生錯誤。
* 變數提升==宣告前不允許使用(暫時性死區)== 不讓開發者在「提升之後」到「賦值之前」的這段期間提取變數。==若未宣告該變數，會回傳錯誤==
```javascript
const pi=3.14;  
console.log(pi);  
pi=3.1422;  //x const變數只能給一次值且一定要給值
console.log(pi);  
const a = []
a[0] = 1//可以改變裡面的值
const b = {}
b.foo = 123//可以改變裡面的值
```


==函式表達式只能使⽤const宣告==
```javascript=
const foo = function() { }
```






---

## var 與 let 的差別
var 與 let 的差別
1. 塊級區域function scope&block scope
1. 變數提升
1. 不允許重複宣告
### 塊級區域scope 是變數可以被取用的區域
* var是函式作用域function scope:
函式會建立自己的作用域，其內的識別字（不管是變數、函式）僅能在這個函式裡面使用。

```javascript

 var a=1;
 if(true){
    var b=2;
 }
 console.log("a",a)//a 1
 console.log("b",b)//b 2
```
==變數 b使用var宣告，var是函式作用域，所以拿得到值==
* let與const是區塊作用域block scope:
由一組大括號包起來的範圍，變數範圍只會存在大括號裡

```javascript

let a=1;
if(true){
    let b=2;//block scope
    console.log("a",a)//a 1
    console.log("b",b)//b 2
}
console.log("a",a)//a 1
console.log("b",b)//undefined,變數b在大括號內定義有值,在大括號外定義是沒有值的


```
==變數 b使用let宣告，b的變數範圍只會存在這個大括號裡，所以在區塊作用域外拿不到值==

### 變數提升（hoisting）
在JavaScript 中另一件有關變數不常見的事, 是你可引用一個較晚宣告的變數並且不會有異常。這個概念被稱為「提升（hoisting）」；
變數在 JavaScript 中是「被提升（hoisted）」或「被抬至（lifted）」到函式（function）或陳述式（statement）的頂部。
然而，==被提升（hoisted）的變數將返回一個未定義的值（undefined）==。所以即使你在使用或者引用這個變數之後才宣告和初始化它，它仍然會返回它是一個未定義的值（undefined）。
* var
 如果我們是後定義,==var會自動幫我們定義undefined== 

```javascript
console.log("a",a)//undefined 
                  //如果我們是後定義,var會自動幫我們定義var a;
console.log("c",c)//not defined 
                  //沒有定義這個變數c
var a=1;
if(true){
   var b=2;
}
```
* let比較嚴謹
不能先執行才定義這個變數,變數要先定義才能執行
```javascript
console.log("a",a)//Cannot access 'a' before initialization
                  //我還沒執行這一段之前你不能使用這個變數
console.log("c",c)//not defined
                  //沒有定義這個變數
        let a=1;
        if(true){
            let b=2;
        }
```
### 不允許重複宣告
* var可以重複宣告

```javascript
var a=1;
var a=5;
if(true){
    var b=2;
}
console.log("a",a)//a 5後面宣告的5把前面宣告的值蓋掉了
console.log("b",b)//b 2

```
* let不可以重複宣告

```javascript
let a=1;
let a=5;
if(true){
    let b=2;
}
console.log("a",a)//Identifier 'a' has already been declared不允許重複宣告
console.log("b",b)//undefined,不再作用域裡

```
（5）暂时性死区： 在使用let、const命令==声明变量之前，该变量都是不可用的==。这在语法上，称为暂时性死区。使用==var不存在暂时性死区==。
（6）初始值设置： 在变量声明时，==var 和 let 可以不用设置初始值==。而==const声明变量必须设置初始值==。
（7）指针指向： let和const都是ES6新增的用于创建变量的语法。 let创建的变量是可以更改指针指向（==可以重新赋值==）。但const声明的变量是不允许改变指针的指向（==不可以重新赋值==）。

作者：CUGGZ
链接：https://juejin.cn/post/6940945178899251230
来源：掘金
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。


---

## 作用域
### var函式作用域:
超過function就不會作用
```javascript

var a=1;
var a=5;
if(true){
    var b=2;
        }
function showVar(){
    var c=3
    console.log("c",c)//c 3
}
showVar()呼叫
console.log("a",a)//a 5 var可以重複宣告
console.log("b",b)//b 2 function作用域
console.log("c",c)//c not defined函式作用域var只要超過函式function的範圍就無法執行
```

### let區塊作用域:
超過區域的大括號就不會作用
```javascript

        let a=1;
        if(true){
            let b=2;
            console.log("a",a)//1
            console.log("b",b)//2
        }
        function showVar(){
            let c=3
            console.log("c",c)//3
        }
        showVar()
        console.log("a",a)//1
        console.log("c",c) c is not defined

```






* 全域變數global variable
* 區域變數local variable

```javascript
        var a=1;//global variable
        var c=5;//global variable
        if(true){
            var b=2;//local variable
        }
        function showVar(){
            var c=3//function scope
            console.log("inside c",c)//inside c 3
        }
        showVar()
        console.log("a",a)//1
        console.log("b",b)//2
        console.log("outside c",c)//outside c 5
```


```javascript
        let a=1;//global variable
        let c=5;//global variable
        if(true){
            let b=2;//local variable
            console.log("a",a)//1
            console.log("b",b)//2
        }
        function showVar(){
            let c=3;//function scope
            console.log("inside c",c)//inside c 3
        }
        showVar()
        console.log("a",a)//1
        //console.log("b",b)
        console.log("outside c",c)//outside c 5
        //let在同一個作用欲下不可以使用同一個變數,在不同作用愈可以使用同一個變數
不用擔心全域變數去影響到區域變數
```
前面沒有var.let的d
```javascript
var a=1;
var c=5;
var d=9;
if(true){
    var b=2;
}
function showVar(){//函式作用域function scope
    var c=3;//區域變數//local variable
    d=12;//全域變數前面沒有var.let
    console.log("inside c",c)//印出inside c 3
    console.log("inside d",d)//印出inside d 12
}
showVar()
console.log("a",a)//a 1
console.log("b",b)//b2
console.log("outside c",c)//印出outside c 5
console.log("outside d",d)//印出outside d 9變成12
d12前面沒有var.let是全域變數,所以這個值會去覆蓋存取前面的全域變數的d
```

[JavaScript基本功修練：Day5 - 宣告變數 - let、const、var](https://ithelp.ithome.com.tw/articles/10240708)