1. 程式人生 > 實用技巧 >04-var、let和const的區別

04-var、let和const的區別

變數是一個用於儲存任意值的命名佔位符。

通用

定義多個變數,逗號隔開

var message="hi",found=false,age="29";

宣告與賦值

var和let允許先聲明後賦值;const不允許,它宣告變數時必須同時初始化變數

var message;	//undifined
message='hi';	//hi
let message;	//undifined
message='hi';	//hi
const age;	//SyntaxError

const宣告的限制只適用於它指向的變數的引用。舉個例子,如果const變數引用的是一個物件,那麼修改這個物件內部的屬性不會受到限制:

const person={};
person.name='xiaoming'

修改變數

var和let允許修改變數的值與型別;而const不允許。

//改變值
var massage='hi';
massage='hello';

//改變型別
var age=1;
age='hello';
const age=19;
age=32	//TypeError:給常量賦值

宣告提升

var定義的變數的宣告會提升;let和const不會。

function foo(){
	console.log(age)
    var age=26
}
foo()//undefined

等價於

function foo(){
    var age
	console.log(age)
    age=26
}
foo()//undefined

因此,var可以反覆定義同一個變數而let和const不可以

function foo(){
    var age=18
    var age=26
    console.log(age)
}
foo()//26
//由於宣告提升,相當於在函式頂部聲明瞭age,後面的定義相當於重新賦值

宣告提升:宣告的變數會提升到函式作用域頂部

重複宣告

var允許重複宣告;let和const不允許。

var name;
var name;
let name;
let name;//SyntaxError:name已被定義過
const name;
const name;//SyntaxError:name已被定義過

宣告冗餘

var name;
let name;//SyntaxError:name已被定義過
let name;
var name;//SyntaxError:name已被定義過

宣告作用域

var宣告的是函式作用域;let和const宣告的是塊級作用域。

function test(){
	var age=2;
    //如果寫成:age=2;表示建立了全域性變數,此時在函式外可以訪問。
}
test()
console.log(age) //ReferenceError

函式作用域指在函式內定義變數,該變數會成為函式的區域性變數,變數會在函式退出時被銷燬。塊級作用域是函式作用域的子集,所以let和const同樣適用於函式作用域。

if(true){
    var age=19;
    console.log(age)//19
}
console.log(age)//19
if(true){
    let age=19;
    console.log(age)//19
}
console.log(name)//ReferenceError:age沒有定義

全域性宣告

var在全域性作用域中宣告的變數會成為window物件的屬性;let和const不會。

var name='lihua';
console.log(window.name)//lihua
var let='lihua';
console.log(window.name)//undefined

全域性作用域:直接編寫在 script 標籤之中或單獨的JS檔案中的JS程式碼,都是全域性作用域;全域性作用域在頁面開啟時建立,頁面關閉時銷燬;

暫時性死區

由於let的變數不會在作用域中提升,所以let不能引用未宣告的變數,在let宣告之前的執行瞬間被稱為“暫時性死區”,在此階段引用任何後面才宣告的變數都會丟擲ReferenceError

console.log(age);//ReferenceError:age沒有定義
let age=18;

for迴圈中的變數宣告

  • 對於var

    迴圈定義的迭代變數會滲透到迴圈體外部。

    for(var i=0;i<5;i++){
      //...
    }
    console.log(i)//5
    
  • 對於let

    迴圈定義的迭代變數不會滲透

    for(let i=0;i<5;i++){
      //...
    }
    console.log(i)//ReferenceError:i沒有定義
    
  • 對於const

    不能用來宣告迭代變數

    for(const i=0;i<5;i++){
        console.log(i)//TypeError:給常量賦值
    }
    

    除非這個變數不會修改

    for(const j=7;i<5;i++){
        console.log(j)//7,7,7,7,7
    }
    
    for(const key in {a:1,b:2}){
        console.log(key)//a,b
    }
    
    for(const value of [1,2,3,4,5]){
        console.log(value)//1,2,3,4,5
    }