let and const
相同點:
let與const用來聲明變量,用法與var類似,但是let與const聲明的變量只在它們命令所在的代碼塊中有效;
let與const聲明的變量不存在變量提升,所以必須在聲明後使用,否則會報錯,沒有賦值會輸出undefined;
//變量聲明前調用會報錯
console.log(a)//報錯
let a=0;
console.log(a)//0
//變量聲明未賦值返回Undefined
let a;
console.log(a)//undefined
如果在塊級作用域中存在用 let和const聲明的變量,那麼這些變量必須在let和const聲明後執行,否則就會報錯;阮一峯老師稱之爲“暫時性死區”
let tmp=0;
if(true){
//在本作用域中已有tmp的聲明,需要在聲明後使用,否則報錯;
tmp=5;//報錯
let tmp;
console.log(tmp)//undefined
tmp=123;
console.log(tmp)//123
}
let和const不允許在同一作用域中,重複聲明同一個變量
{
//重複聲明會報錯
let a=0;
var a=5;//Identifier 'a' has already been declared
let b=0;
b=5;//Identifier 'a' has already been declared
}
不同點:
const聲明一個只讀的常量,一旦聲明常量值不能改變;用const聲明必須馬上賦值 否則報錯;
//const 必須聲明後必須馬上賦值 不然會報錯
const a;//Missing initializer in const declaration
//聲明後對於簡單數據類型來說,值是不能改變的(常量),否則就會報錯;
const a=10;
a=20;//Assignment to constant variable.
const所聲明的變量對於簡單的數據類型(數值,字符串,布爾值)來說算是固定的常量,但是對於複合類型的數據(對象,數組)來說,const只能保證這個變量指向的內存地址不變,對象的值與數組的值還是可以修改的。
const foo={};
foo.prop=123;
console.log(foo.prop)//123
上面代碼就是修改了foo這個變量的prop屬性的值,因爲prop屬性屬於foo這個對象,使用的是foo的內存地址,所以const不會報錯;
但是,如果試圖去修改foo對象的話就會報錯;
const foo={};
foo={};//TypeError: Assignment to constant variable.
數組同理
//調用屬性不會報錯
const arr=[];
arr.push('hello');
arr.length=0;
//想要修改對象就會報錯
const arr=[];
arr=[];//TypeError: Assignment to constant variable.
let&for循環
for循環中 如果用var來初始化i的值,聲明的是一個全局的變量i;
用let來聲明i,每次循環都會創建一個新的變量i;
//使用var初始化變量
var arr=[];
for(var i=0;i<10;i++){
arr[i]=function (){
console.log(i)
}
}
arr[6]()//10
上面代碼中,變量i是var命令聲明的,在全局範圍內都有效,所以全局只有一個變量i。每一次循環,變量i的值都會發生改變,而循環內被賦給數組a的函數內部的console.log(i),裏面的i指向的就是全局的i。也就是說,所有數組a的成員裏面的i,指向的都是同一個i,導致運行時輸出的是最後一輪的i的值,也就是10。
如果使用let,聲明的變量僅在塊級作用域內有效,最後輸出的是6。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
上面代碼中,變量i是let聲明的,當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變量,所以最後輸出的是6。你可能會問,如果每一輪循環的變量i都是重新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是因爲 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變量i時,就在上一輪循環的基礎上進行計算。
另外,for循環還有一個特別之處,就是設置循環變量的那部分是一個父作用域,而循環體內部是一個單獨的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面代碼正確運行,輸出了3次abc。這表明函數內部的變量i與循環變量i不在同一個作用域,有各自單獨的作用域。
(上面是學習阮一峯老師的ES6入門記錄下來的)