# 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)