如果你是一個前端工程師,那么JavaScript作用域你一定不會陌生。你知道的可能是 JavaScript中有: 傳統(tǒng)的函數(shù)級作用域和全局作用域、ES6 let const 的塊級作用域。但是還有一個你不知道的塊級作用域的存在,今天我們就來扒一扒這些鮮為人知的小秘密我們先來看看下面這個段代碼,請思考一下結(jié)果是什么。
想必你心中已經(jīng)有了結(jié)果
正確答案是3 2
你答對了嗎?答案結(jié)果是否有些意外呢?好了,我們來看看為什么會出現(xiàn)這個答案首先我們需要先了解以下基本知識
聲明提前
聲明提前指的是JS引擎在執(zhí)行之前對代碼進行的預(yù)解析(為了提高執(zhí)行效率) 具體的來說就是使用(var)聲明變量和(function)聲明的函數(shù)正預(yù)編譯階段將其提升到了作用域的頂部
全局變量聲明
函數(shù)作用域變量聲明
函數(shù)聲明
函數(shù)表達式聲明
函數(shù)塊級作用域
通過下面代碼我們可以知道 變量的聲明是沒有塊級作用域的,if語句塊中聲明的變量foo會提升到全局作用域并初始化值為undefined
我們再看看函數(shù)的情況
上面這個例子告訴我們 函數(shù)foo提升到了if語句塊的頂部,但是沒有提升到全局作用域的頂部。但全局作用域中存有一個名為foo的變量 在代碼執(zhí)行后同步成了函數(shù)foo
同步?為什么會有同步?我們來看看觀察上帝視角的神器 ———— 斷點調(diào)試
我這邊監(jiān)聽了 foo 變量和 window.foo 大家請注意一下它的變化
同時我們也關(guān)注一下 Scope 作用域
我們看到Scope中只有全局作用域 foo和window.foo的只都是undefined
代碼執(zhí)行到if語句塊中 我們再Scope中又發(fā)現(xiàn)了一個新的塊級作用域 當前塊級作用域foo的值被賦值為一個函數(shù)(函數(shù)提升) 而全局作用域中的foo依舊是undefined
代碼繼續(xù)往后執(zhí)行 執(zhí)行函數(shù)的賦值 block作用域依然存在 我把幾個變量的值使用箭頭進行了對應(yīng)
神奇的地方來了 在函數(shù)執(zhí)行賦值后 塊級作用域消失 而全局變量的foo同步成了剛才塊級作用域的foo
回歸原題
我們對foo變量進行隔行輸出 看看結(jié)果
結(jié)合上面斷點測試的結(jié)果大家可以發(fā)現(xiàn),函數(shù)在代碼塊中聲明會提前到塊級作用域頂部,預(yù)編譯結(jié)束后開始執(zhí)行代碼 在執(zhí)行階段任然會執(zhí)行函數(shù)的賦值操作,其實是函數(shù)賦值的第二次執(zhí)行(第一次在預(yù)編譯階段) 第二次的賦值執(zhí)行的意義是確認當前 函數(shù)/全局 作用域能準確的檢索到函數(shù) 所以講函數(shù)同步到了 當前的函數(shù)或全局作用域中。更多關(guān)于前端培訓的問題,歡迎咨詢千鋒教育在線名師,如果想要了解我們的師資、課程、項目實操的話可以點擊咨詢課程顧問,獲取試聽資格來試聽我們的課程,在線零距離接觸千鋒教育大咖名師,讓你輕松從入門到精通。
注:本文部分文字和圖片來源于網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系刪除。版權(quán)歸原作者所有!