1.變數:var,let,const
- 2020 年 10 月 3 日
- 筆記
- JS高級程式設計筆記
var在ECMAScript的所有版本中都可以使用,而const和let只能在ES6及更晚的版本中使用。
var,let,const三個關鍵字的區別
var:
1)聲明作用域:在函數內部,使用var定義一個變數(局部變數),在函數被調用完之後,該變數會被立即銷毀。在定義變數時如果省略var,就會創建一個全局變數(不建議在局部作用域中定義全局變數,難維護,而且在嚴格模式下,會導致拋出ReferenceError)。
2)聲明提升:把所有變數聲明都拉到函數作用域的頂部。
function foo(){ console.log(age); var age = 18; }
等價於
function foo(){ var age; console.log(age); age = 18; } foo();//undefined
3)可以反覆多次使用var聲明同一個變數
function foo(){ var age = 16; var age = 1; var age = 2; console.log(age); } foo();//2
4)全局聲明:使用var在全局作用域中聲明的變數會成為window對象的屬性。
var age = 18; console.log(window.age);//18
let:
1)聲明作用域:let聲明的是塊作用域,而var聲明的是函數作用域。塊作用域是函數作用域的子集,所以var作用域的限制同時也適用於let
//var if(true){ var age = 18; console.log(age);//18 } console.log(age);//18
//let if(true){ let age = 18; console.log(age);//18 } console.log(age);//ReferenceError:age沒有定義
2)聲明提升:let聲明的變數不會在作用域中被提升
3)不可以在一個塊中反覆多次使用let聲明同一個變數
let age; let age;//SyntaxError,標識符age已經聲明過了
4)全局聲明:使用let在全局作用域中聲明的變數不會成為window對象的屬性,但是var聲明的變數會。
let age = 18; console.log(window.age);//undefined
5)條件聲明:在使用var聲明變數時,由於聲明會被提升,JS會自動將多餘的聲明在作用域頂部合併為一個聲明。而因為let的作用域是塊,所以不可能檢查前面是否已經使用let聲明過同名變數。因此對於let,不能依賴條件聲明模式。
6)for循環中的let聲明:在用let聲明迭代變數時,JS在後台會為每個迭代變數聲明一個新的迭代變數,每個setTimeout引用的都是不同的迭代變數。for-in 和for-of都適用。
for(var i=0;1<5;i++){} console.log(i); //5 for(let i=0;1<5;i++){} console.log(i); //ReferenceError:i沒有定義
for(var i=0;1<5;i++){ setTimeout(()=>console.log(i),0); } //會輸出5,5,5,5,5 for(let i=0;1<5;i++){ setTimeout(()=>console.log(i),0); } //會輸出0,1,2,3,4
const:
1)const的行為和let基本相同,唯一的區別是const它聲明變數時必須同時初始化變數,且嘗試修改const聲明的變數會導致運行時錯誤(TypeError)。
2)不允許重複聲明
3)作用域也是塊
4)const聲明的限制只適用於它指向的變數的引用。換句話說,如果const變數引用的是一個對象,那麼修改這個對象內部的屬性並不違反const的限制。
const person = {};
person.name = "QiuYing";
5)不能用const聲明迭代變數,因為迭代變數會自增。但是可以聲明一個不會被修改的for循環變數。這對for-in 和for-of循環特別有意義。
聲明風格及最佳實踐:先使用const,let次之,不使用var