一、JavaScript變量創建到訪問賦值的過程
- 創建 create/declare
- 初始化 initialize
- 賦值 assign
1、函數的提升
// 函數這種變量聲明,首先會創建變量,再初始化,最后開始執行代碼 doSth(); function doSth(){ var a = 1; var b = 2; console.log(a,b); }
- 1、找到function聲明的變量,在環境中創建這些變量
- 2、初始化這些變量,本例中將doSth(){ var a = 1; var b = 2; console.log(a,b); }的值初始化到 doSth
- 3、執行doSth這個函數
2、var變量的提升
// 此例子跟函數變量提升一致,但是var變量提升過程不一樣 // 首先 創建變量,再初始化,隨即執行代碼(在此之前沒有賦值) doSth(); function doSth(){ console.log(a); var a = 1; var b = 2; console.log(b); }
- 1、函數內部收集var 變量聲明,並在環境中創建這些變量,本例子中的var a,var b ;
- 2、變量初始化,及var a = undefined ;var b = undefined;
- 3、開始在環境中執行代碼:從第一行console.log(a);開始,此時a為undefined,第二行 var a =1 ;給a 賦值;第三行給b賦值;第四行輸出2;
3、let的變量提升過程
// 首先創建變量,隨即執行代碼(在此之前沒有賦值),執行代碼的第一次賦值即為初始化,若后續再次賦值,則是真的賦值; { console.log(x); let x = 1; x = 2; let y = 3; console.log(y) }
- 1、收集所有的let聲明:x 及y;創建這些變量;(此時並沒有初始化)
- 2、執行代碼:
// 執行第一行代碼: console.log(x); // 會拋出錯誤“Uncaught ReferenceError: x is not defined” // 執行第二行代碼 let x = 1;// 初始化x =1 ,此時為初始化(並不是賦值)。初始化的值為1 // 執行第三行代碼 x = 2 // 此時為x賦值2 // 執行第四行代碼 let y = 3; 此時為變量y初始化,初始化的值為3 // 執行第五行代碼 console.log(y)// 3
4、臨時死區TDZ(Temporal Dead Zone)
在let /const 變量聲明前調用該變量都是放到這個TDZ中,如果引用或者訪問該變量了就會報錯Uncaught ReferenceError
// 源代碼 { a = 2; let a ; a = 3 } // 加入TDZ后的代碼 { // 變量提升,創建 let a ; // TDZ 區開始--- a = 2; a ;//此時等同於a 初始化為undefined // TDZ 區結束--- // 此時可以訪問a a = 3 }