首先來看一段代碼javascript
console.log(a) var a = 2;
輸出結果是2,正常來講JS若是是逐行向下執行,那麼應該輸出undefined,爲什麼此處輸出2呢?
緣由在於JS在執行前都會進行編譯(一般就在執行前),在編譯過程當中包括變量和函數在內的全部聲明都會被處理。java
是指在 JavaScript 代碼執行前的編譯過程當中,JavaScript 引擎把變量的聲明部分和函數的聲明部分提高到代碼開頭的「行爲」。變量被提高後,會給變量設置默認undefined。瀏覽器
首先咱們要知道定義一個JS變量分爲三個階段svg
下面咱們分別來看看var、let、function 和 const的過程函數
function fn() { var x = 1; } fn();
由以上步驟可知,var 聲明會在代碼執行以前就將建立變量,並將其初始化爲 undefined。即建立和初始化會被提高spa
fn(); function fn() { console.log(1); }
由以上步驟可知,function 的「建立」「初始化」和「賦值」都被提高了3d
{ let x = 1; x = 2; }
由以上步驟可知,let只有建立過程會提高,初始化和賦值都不會提高,因此會造成暫時性死區,這也是爲何在定義前使用let會拋錯。code
暫時性死區,就是不能在初始化以前,使用變量cdn
{ console.log(x); const x = 1; }
由以上步驟可知,const的建立過程也會提高,可是與let不一樣之處在於const只有建立和初始化兩個過程,沒有賦值過程。若不初始化則會直接拋錯對象
何爲函數優先,來看一下下面的代碼👇
foo(); var foo; function foo() { console.log(1) }
實際上輸出值會是1,由於當變量聲明和函數聲明同時存在時,函數聲明優先於變量聲明,即函數聲明會覆蓋變量聲明。緣由在於函數的賦值過程也會提高。那有人可能有疑問,若是將var變成let呢?結果爲foo不容許被重複聲明。
執行上下文中存在一個變量環境的對象(Viriable Environment),該對象中保存了變量提高的內容。而let,const則存在詞法環境中。
瀏覽器原理與實踐