變數的有效範圍
在ES6之前,JS變數有效範圍的最小單位是以function
做分界。
在ES6之後,有了let
和const
分別定義了「變數」和「常數」,他們與var
不從的地方在於,
他們是用大括號{}來切分的,而且let
不能重複宣告變數。
ex:
1 | var x = 10; |
提升(Hoisting)
在變數宣告的部分,編譯器會自動地將’宣告’的那部分,提升到該變數被定義的範圍的最上方。
注意!!是只有’宣告’的部分被提升喔,被定義的部分是會保留在原地的。
ex:
1 | var x = 1; |
Question1. ??? 的結果是undefined
!!
Question2. 倒數第二行印出來的結果,居然是150 !!!
讓我們來解析一下上面這行程式碼
首先,先記得上面講的變數的’宣告’,會先被提升到該變數被宣告範圍的最上方
ex:
1 | var x = 1; |
Ans1:
由上面的例子可以看出來在doSomething的變數x被宣告的部分,被提升函數中的最上方位置,但是,此時,x還沒有被賦值,所以,
下面console的結果才會是undefined
。
Ans2:
一樣是因為在domSomething的函式中的變數x是區域變數,它跟外面的全域變數x是不同人,所以,在doSomething調用的x,是區域變數x,故其值為100,
也因為是這樣,100 + 50 = 150,結果才會是150。
let/const 宣告的暫時性死區(Temporal Dead Zone, TDZ)
首先,要知道let
宣告是無法重複宣告的,而且,let
宣告是沒有提升的特性的。
也因為let
沒有提升的特性,也造成它有死區的狀況出現。
ex:
1 | ---var宣告--- |
由上面個範例可以看的出來,在var
宣告的範例中,因為,var
有提升的特性,只是賦值得那部分會留在原地,所以,在console印出的結果是undefined
。
而由let宣告的那個範例,因為,let
沒有提升的特性,所以,console那段,編譯器根本就不知道變數x是誰, 而這段就是let
的死區,所以,才會報出ReferenceError
的錯誤。
函式的提升特性
注意!! 「函式宣告」 方式定義的函式有提升的特性。 而用「函式運算式」方式定義的函式式沒有提升的特性。
ex:
1 | ---函式宣告--- |
另外,變數提升的部分只有”宣告的部分被提升”。
而函式宣告提升的部分”整個函式定義的內容都被提升”。
全域變數 和 區域變數
在JavaScript中,「全域變數」精確地來講是指「全域物件的屬性」。
「全域物件」是什麼?
以瀏覽器來講,「全域物件」指的是window。
ex:
1 | var a = 10; // 全域變數 |
ex2:
1 | function func(num){ |