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