JS變數提升和函式提升
1.變數提升
在ES6之前,我們宣告一個變數需要用到var關鍵字,用var來宣告的變數就存在變數提升的特性。
上述程式碼粗略來講解,在上述程式碼中存在全域性作用域和函式作用域,在兩個作用域中都聲明瞭變數a。在fn函式執行console.log(a)的時候,先會在自身所處在的函式作用域中找到變數a,
如果沒有找到,就會去全域性作用域中找。
在fn函式作用域中我們可以看到a變數宣告並賦值了,但是它處於console.log(a)語句的下方,按照正常的邏輯,它不應該找到的是外層定義的a嗎?但是結果恰恰相反。
程式碼執行流程:
我們可以根據位置來把程式碼分為全域性程式碼和函式(區域性)程式碼。在執行全域性程式碼前,首先將window新增為全域性執行上下文,之後對全域性資料做預處理工作:
(1)找到var關鍵宣告的變數,賦值為undefined,且新增為window的屬性。=>變數提升
(2)將function宣告的變數賦值fun(),新增為window屬性。=>函式提升
(3)this =>賦值window
在預處理結束後,開始執行全域性程式碼。
函式程式碼執行流程也和上述大同小異,這裡涉及到執行上下文,就不細講了,後續會補充。
所以我們可以這樣理解這行程式碼
最後的結果自然就是undefined。這就是js存在的變數提升。
2.函式提升
函式提升和變數提升的原理一樣,區別就是在於,函式提升已經建立好了函式物件,而變數提升賦值為undefined,可以理解為變數宣告提升。
3.拓展
(1)var fn = function(){}和function fn(){}的區別:前者為變數提升,後者為函式提升。
如果是用變數提升來宣告函式,如果在此前呼叫該函式,此時的函式物件並沒有建立,變數fn2賦值為undefined,所以瀏覽器不能識別,把它當做函式來呼叫,所以最後報錯。
(2)在js中,函式是第一公民
被覆蓋的不是函式fn,而是var fn =3;
結果:
&n