你以為JS拿來就乖乖照著我們打的一行一行跑嗎?太天真了,我說我~~
變數怎麼存,存哪裡,在哪裡叫得到變數出來?我們會連續幾天,討論這個問題~
一句話解釋,預編譯是幹蛤的?
根據宣告變數、宣告function的關鍵字,在內存開闢位置給變數、function
執行前一刻,做預編譯:
建立形參(形式參數)、
建立變數
特別注意:形參和var 初始化undefined;let 和const沒有初始化
賦值實參(實際參數)給形參
建立function(此時不管function的body是甚麼,執行時才看)
開始執行(function和變數這裡才賦值)


function outerFun(){
	function innerFun(){};
	innterFun();
};
outerFun();
window object在預編譯的step4:宣告function時,建立了outerFun
window object執行window object執行中,執行到outerFun()時:
outerFun代碼的前一刻,預編譯outerFun
outerFun時,建立了innerFun
outerFun執行outerFun執行中,執行到innerFun()時:
innerFun代碼的前一刻,預編譯innerFun
innerFun執行整理一下邏輯:
試問:執行時,我愛多早呼叫變數、呼叫function,愛多早就多早,不會報錯,頂多undefined?
是的呀~~因為我已經把宣告變數、宣告function這件事情,提升了嘛~
(這裡也還不是提升的完整版
受限於let有一丟丟的麻煩,這裡只先討論var變數和function
一定會有完整版的放心~~)
var變數的提升:undefined
undefined
→故:var變數的提升,得undefined
function的提升:完整的function(不是空殼function)
小整理:var變數、function甚麼時後有值的(可以往上對照俄羅斯娃娃那裏)

猜猜:是不是用原始值或引用值來區分能不能完整提升?
.
.
.
.
.
.
想多了(我就是這樣誤以為)
object,array都是引用值的一種,但他們就不像function object可以整塊完整被提升。
console.dir(o) //undefined
console.dir(b) //undefined
console.dir(f) //f()
var o={
    'name':'小o',
    '白花':'可曾枯萎呀'
}
var b=['輕聲唱著','少年的模樣','會悲傷會幻想']
function f(){
    var name='別去打擾她'
}
//部分歌詞:<<旅行家說>> 毛不易 
至於為甚麼只有function可以有這個好康,平平都是引用值,為甚麼object和array沒有呢?
我個人的想像是,因為var變數的作用域(有效範圍)是以function為界,所以才會以function做為單位進行提升。
也不是所有function都會乖乖地提升,那到底是誰怎麼不乖呢?要拜乖乖?
fun1();  //1
fun2();  //Uncaught TypeError: fun2 is not a function
//function聲明
function fun1(){console.log(1)};
//function表達式
var fun2=function(){console.log(2)}; 
function表達式雖然提升失敗,被說fun2不是一個function不被承認QQ,
但並沒有破壞規則,規則還是原本那個規則喔~~來,上原因
GO{
	fun1 : function fun1(){......},
	fun2 : undefined
}
沒錯,因為他電腦看到var fun2=,就覺得他是一個原始值,不是function引用值。
殊不知後面等於一個function。失算失算
小結論:能不能像function宣告完整被提升的關鍵因素,是function關鍵字