為什么要將這些內容放在一起,因為他們都跟初始化有關系,我們慢慢說吧,
我們在代碼中,都會宣告變數、函式和物件,然后由瀏覽器解釋器(下面簡稱瀏覽器)執行;
我們還說過,變數和物件的記憶體結構;
那么,是什么時候,我們宣告的變數和物件,被瀏覽器分配記憶體了呢?
我們使用不同的宣告方式,瀏覽器分配記憶體的順序是一樣的嗎?
window物件
我們先來看一個物件window,這個物件代表什么呢?
顧名思義,它代表一個視窗,一個瀏覽器視窗;
當我們用瀏覽器打開一個頁面的時候,這個window物件就被初始化創建了;
這個window物件,出生就自帶很多方法,包括JS內置函式和瀏覽器視窗函式;
所以下面的代碼才能夠在什么都沒有的情況下,輸出window物件:

可以看到,alert()也是window物件的一個方法,其實console.log()也是;
也就是說,上面的代碼,其實是window.console.log(),只是省略了window而已;
window物件是一個非常值得細致研究的物件,但是這里就不贅述了,我們還有很多內容要說;
總之記住一點,window物件代表的是整個瀏覽器視窗,它的范圍是最大的,它是最早被創建的物件;
變數的作用域
變數的作用域,其實就是指它的可見性,分為全域作用域和區域作用域:
-
區域作用域
先來說明一下代碼塊的概念;
凡是用大括號
{}括起來的都是代碼塊,包括函式體、回圈體,以及大括號本身等等;在代碼塊中宣告的變數,它就只在代碼塊中可見,代碼塊外面是無法訪問到的;
- 因為代碼塊只會在執行時用到,所以代碼塊中的變數的生命周期,也就是執行代碼塊的時候才會創建,而執行結束以后就會被垃圾回收;比如呼叫函式時,變數被創建,呼叫結束,變數就會被垃圾回收;
- 因為大括號可以嵌套,所以外層代碼塊的變數,內層代碼塊可以訪問到;但是內層代碼塊的變數,外層代碼塊訪問不到;
- 因為內外層代碼塊的可見性不一致,內層代碼塊可能創建和外層代碼塊同名的變數,此時內層代碼塊使用變數時,采用就近原則,也即使用離內層代碼塊最近的變數;
具體看下面的代碼吧:

如上圖所示,每個代碼塊中的變數a的作用域,都用框表示出來了;
值得一提的是,因為函式的特殊性,函式的區域性比其他代碼塊更強,這在關鍵字
var那里體現的最明顯, -
全域作用域
那么全域作用域的概念就很清晰了,不在任何
{}代碼塊中的,直接在script標簽中宣告的變數,都具有全域作用域;那么它的生命周期,也就是打開一個瀏覽器視窗的時候被創建,關閉一個瀏覽器視窗時才會被垃圾回收;
關鍵字var和let
還記得我們宣告變數的三種方式嗎(因為const和let的行為一致,這里就不討論const了)?
我們先討論全域作用域的變數宣告的區別:
-
不使用關鍵字


可以看到,這種宣告方式,變數會成為
window物件的屬性,也就是隨著window物件一起初始化了;但是圖二告訴我們,它似乎不能被訪問,即此時記憶體并沒有變數a,所以輸出了
a is not defined,這是為什么?我也不知道;所以非常不推薦這種宣告方式;
-
使用關鍵字
var

可以看到,這種宣告方式,變數會成為
window物件的屬性,也就是隨著window物件一起初始化,開辟了一塊記憶體空間用來存盤變數a;但是此時變數a還沒有被賦值,所以輸出了
undefined,并不會報錯;這也是為什么不推薦使用這種方式來宣告變數,因為它的全域作用域太大,甚至在被賦值前,就可以訪問而不報錯;
-
使用關鍵字
let

可以看到,這種宣告方式,變數不會成為
window物件的屬性;但是此時變數a,實際上已經開辟了記憶體區域了,但是還沒有初始化,所以才會報錯
Cannot access 'a' before initialization;這是一種符號大多數編程語言的關于變數宣告的處理方式,也是ES6新推出的,用來避免
var的宣告方式,也是被推薦的宣告方式;
再來說一下區域作用域的一些特殊情況,主要是關鍵字var:
先看下面代碼的輸出結果:


可以看到,哪怕是在代碼塊中,使用var和無關鍵字的宣告方式,依然還是會成為window物件的屬性,具有全域作用域;而let宣告的變數,就具有正常的區域作用域,
再看下面代碼的輸出結果:

可以看到,在函式體的代碼塊中,三種宣告方式具有相同的區域作用域,函式體外部都訪問不到;
這說明,var雖然在其他代碼塊中不具有區域作用域,但是在函式體中卻具有區域作用域,可以稱之為函式作用域;
總結:
- 除函式體外,在任何地方使用
var或者無關鍵字的宣告方式,變數都是作為window物件的屬性,具有全域作用域; - 在函式體中,無論何種宣告方式,都是區域變數,具有區域作用域;
let以及const的作用域表現,是最正常的,符合大多數編程語言對變數作用域的定義;- 推薦使用
let以及const來宣告變數,酌情考慮使用var來宣告變數,最好不要使用無關鍵字的方式來宣告變數;
關鍵字function
宣告一個函式的時候,我們可以使用關鍵字function進行宣告;
我們先看下面代碼的輸出結果:

按照代碼從上至下的順序執行,我們可以看到,盡管函式aaa的宣告代碼,是在列印和呼叫aaa的代碼之后,依然列印和呼叫成功了;
說明,當瀏覽器執行代碼的時候,函式宣告是先執行的,并且它成為了window物件的一個方法;
注意:
- 只有使用
function關鍵字才會這樣,使用函式運算式和箭頭函式去宣告函式的時候,因為有個賦值給變數的操作,所以它是一個執行陳述句,瀏覽器會按照順序去執行; - 只有直接在script標簽中宣告才會這樣,在其他任何代碼塊即在
{}中進行宣告,因為代碼塊也是執行陳述句,瀏覽器會按照順序去執行;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/539675.html
標籤:其他
