13-1 什麼是變數領域 Scope ? 靜態 vs 動態作用域 全域區域變數
Lesson: 13-1 什麼是變數領域 Scope ? 靜態 vs 動態作用域 全域區域變數
13-1 什麼是變數領域 Scope ? 靜態 vs 動態作用域 全域區域變數
講義
1. 什麼是變數領域 (Scope)?
作用域決定了變數的「可存取範圍」。如果你在某個範圍外嘗試存取變數,程式會報錯(例如 xxx is not defined)。
2. 靜態作用域 (Static Scope / Lexical Scope)
JavaScript 採用的是 靜態作用域。
- 特點:變數的作用域在「函式宣告(寫好程式碼)時」就已經決定,而不是在「執行時」決定。
- 優點:程式的執行結果更容易預測與追蹤,不會因為呼叫函式的順序不同而產生混亂。
3. 全域變數 vs. 區域變數
- 全域變數 (Global Variable):
- 宣告在函式外部的變數。
- 特性:在程式的任何地方都可以存取。在瀏覽器環境中,它們會依附在
window物件下。
- 區域變數 (Local Variable):
- 宣告在函式內部的變數。
- 特性:只有該函式內部可以使用。一旦函式執行結束,該變數通常會被銷毀,外部無法讀取。
4. 變數尋找邏輯 (Scope Chain)
當 JavaScript 在執行一段程式碼需要用到變數 x 時:
- 先檢查當下的「區域範圍」是否有宣告
x? - 如果沒有,就往「外一層範圍」尋找。
- 一層一層往外找,最後會找到「全域範圍」。
- 如果連全域都沒有,則丟出錯誤。
- 重要觀念:「內部」可以看到「外部」的變數,但「外部」無法看到「內部」的區域變數。
影片逐字稿 (AI 生成)
現在我們進入第13章 Scope 變數領域那我們要開始來了解不同的區塊scope 可以做什麼事情所以我們要開始學習 痊癒變數 區域變數 還有closure好了 十三之一 我們開始來看變數領域 痊癒變數 還有痊癒變數的取用首先 什麼是變數領域就是我們可以講說它是它的作用域就是說它是一個scope那一旦超出這個範圍 你就會拿不到這個變數OK 比如說外面的拿不到裡面的東西好的那 JavaScript 是一個靜態作用域就是 static scope那這樣子 就有一些語言也是就是 JavaScript Java Python 都是那這樣子呢 有什麼好處這樣子的好處是就是它是就是更好預測的跟動態的作用域來看它是比較好預測那動態作用域是變數只會隨著每一次使用方選而重新定義所以你每次在用方選的時候它就會重新再定義一次就會增加 難以預測性OK所以動態的會很依賴它執行的先後順序會更依賴它這個方選在什麼時候執行然後它的 define 會更不一樣好了 那在程式裡面呢這件事情是很重要的就是說難以預測就是對程式來講不好因為難以預測你就很難去猜測它在那個時候跑的時候狀況是怎麼樣就像現在大家在跑回圈的時候可能自己也很難去預測說到底跑出來的結果還是怎麼樣所以你才要就是一直不斷的在跑改一些小東西然後你才慢慢的比較知道可以預測自己寫這個code到底會不會到底在幹嘛到底會不會有可能出錯但是很重要的一件事情就是預測性假如越高就是會比較穩定然後多人在做的時候都比較就是比較穩定比較不會出錯比較不會有一些很奇怪的特定例子跑出來好的 我們這邊來看一下這個例子那我們有兩個function一個是function1一個是function2那x我們先寫varx是外部變數然後在這邊function1我們在declare的時候呢我們就已經拿x那其實在作用域的時候他會怎樣他拿這個x的時候他會先去找function1裡面有沒有這個x他發現你根本沒有declare你根本沒有宣告x他就會開始往外面找外面有一個x然後就外部變數所以他就會把這個x當作是它的console所以你之後你在跑function1的時候呢他就會跑出外部變數好 那我們後面再定義了function2然後function2我們有一個varx然後他叫內部變數那這邊的問題會是說他叫內部變數這個function1我到底是會去找這個function1到底是這個x到底是找這上面的這個x還是去找外面的這個x那因為JavaScript是靜態領域的所以當他在宣告的時候他就會先把x在哪裡先找好所以當他在這裡 function宣告的時候他找到的這個x就是外面的這個x而不是這邊再去動態去找外面大家這樣可以理解嗎假如他是動態作用域的話他會怎樣他在執行這個function的時候他才去找x那這個時候他找到x就是內部變數因為他在執行的時候才去找可是JavaScript是靜態作用域所以他在定義的時候我在寫這個function的時候他就已經把x已經說好這裡面沒有那找外面就直接找到外面這裡所以我在用的時候他都不太會變好這是這一張要講的事情那我們跑跑看我們有一個var然後x等於我直接用英文out好不好然後我們然後然後這邊so.logx然後我們在會去定義一個varx等於1然後我們在這邊會去執行function1然後在外面還有執行什麼執行function2對因為你這邊定義完了以後你要執行它嘛對不對function2好這時候呢你看我們已經我們這邊定義兩個function對不對在這邊才去執行function2OK那這邊在定義的時候他就已經去找到這個x他在定義這個變數在定義這個function的時候已經把這個x已經找到外面這個x所以他會找到out這個值而不是像動態定義如果是動態作用域的話他才是就是在執行的時候才去找所以大家記得就是JavaScript在定義的時候他就會先把這個x先找好所以這個x就不會影響這個在執行的狀況好的我們講全域變數我們在很前面的時候已經有提過全域變數那全域變數呢就是在講說整個document就是整個document就是對於JavaScript來講就是一個全域那如果沒有用var宣告的話那他自動就會長在document下面就是一個全域的屬性那在JavaScript裡面最上層的東西是windowOK所以在window下面就是全域變數都會依附在window底下好的那變數JavaScript裡面變數宣告以後就有不可刪除的特性那以宣告的變數是全域物件裡的一個不可變更的屬性那你也可以用函式去改變全域變數的值好那如果我們有一些變數是宣告在呃function裡面的那我們在外面我們是讀不到這裡面的的因為它的作用域我們也有提到嘛var的作用域在哪裡var的作用域是不是在function就會就是外面會讀不到因為它的作用域只有在單獨的那個function裡面比如說像這個inner這個inner這個inner其實就是區域變數它只有在varinner這裡面這個function它的inner值才是inner那在外面你去找inner這個變數它會跟你講說诶It’s not defined你根本沒有你根本沒有跟我講有inner這個變數啊可是在這個function裡面inner就是有用到inner所以這個inner的作用域只有在這一個方式裡面OK那像這一個get global的這個a這個a他會先找這一個function的作用域他找他沒有這個區域變數a所以他會找外面他會發現這個全域變數OK那我們跑一下我這一段code是不是要放在我還是我放下去好首先我們有一個變數全域變數叫做a然後它的值是global然後然後我們有一個function然後它的它的名字是get global在這裡面呢它會console log一個a然後呢在這邊我們會去執行這個程式對不對執行這個function就是我們去call這個functioncall functionget global然後呢在這邊然後呢在這邊我們會去執行這個程式對不對執行這個function就是我們去call這個functioncall functionget globalglobal好這時候它去call這個function這個a它在裡面沒有區域變數所以它直接全域變數a就直接call出來好的那如果說像這個例子我們有一個function叫做varinner然後varinner裡面有一個嗯varinner對不對然後呢它叫做inner它裡面是字串然後這個字串裡面是inner好那我們建好這個varinner以後呢就算我們有去執行它我們有執行它我們在外面叫inner的時候還是找不到這個東西OK因為這個inner只有在function裡面才這個inner才會有作用可是你在外面你根本就沒有叫過這個東西所以外面是讀不到裡面因為作用域的關係好的這是13-1
影片逐字稿largev2
現在我們進入第十三章 Scope 變數領域那我們要開始來了解不同的區塊 Scope 可以做什麼事情所以我們要開始學習 全域變數 區域變數 還有 Closure好了 十三之一 我們開始來看變數領域 全域變數 還有全域變數的取用首先 什麼是變數領域就是我們可以講說 它是它的作用域 就是說它是一個 Scope那一旦超出這個範圍 你就會拿不到這個變數比如說外面的拿不到裡面的東西好的那 JavaScript 是一個靜態作用域 就是 Static Scope那這樣子的 就有一些語言也是 就是 JavaScript、Java、Python 都是那這樣子的有什麼好處這樣子的好處是 它是更好預測的跟動態的作用域來看 它是比較好預測那動態作用域是 變數值會隨著每一次使用 function 而重新定義所以你每次在用 function 的時候 它就會重新再定義一次那這樣子其實就會增加難以預測性所以動態會很依賴它執行的先後順序會更依賴它這個 function 在什麼時候執行然後它的 define 會更不一樣好了 那在程式裡面 這件事情是很重要的就是說難以預測 就是對程式來講不好因為難以預測 你就很難去猜測 它在那個時候跑的時候狀況是怎麼樣就像現在大家在跑迴圈的時候 可能自己也很難去預測說到底跑出來的結果會是怎麼樣所以你才要一直不斷的在跑 改一些小東西然後你才慢慢的比較知道 可以預測自己寫這個 code 到底會不會到底在幹嘛 然後到底會不會有可能出錯所以寫程式很重要的一件事情就是預測性假如越高 就是會比較穩定然後多人在做的時候都比較穩定 比較不會出錯比較不會有一些很奇怪的特定例子跑出來好的 我們這邊來看一下這個例子那我們有兩個 function一個是 function1 一個是 function2那我們先寫 var x 是外部變數然後在這邊 function1 我們在 declare 的時候呢我們就已經拿 x那其實在作用域的時候呢它會怎樣 當你拿這個 x 的時候它會先去找 function1 裡面有沒有這個 x發現 function1 你根本沒有 declare 你根本沒有宣告 x它就會開始往外面找然後它找到外面有一個 x然後就外部變數 所以它就會把這個 x 單位當作是它的 console log所以之後你在跑 function1 的時候呢它就會跑出外部變數好 那我們後面再定義了 function2那 function2 我們有一個 var x然後它叫內部變數那這邊的問題會是說它叫內部變數 那我 function1 我到底是會去找這個 function1 的 x 到底是找這上面的這個 x還是去找外面的這個 x那因為 JavaScript 是靜態領域的所以當它在宣告的時候它就會先把 x 在哪裡先找好所以當它在這裡 function 宣告的時候它找到的這個 x 就是外面的這個 x而不是這邊再去動態去找外面大家這樣可以理解嗎假如它是動態作用域的話 它會怎樣它在執行這個 function 的時候它才去找 x那這個時候它找到 x 就是內部變數因為它在執行的時候才去找可是 JavaScript 是靜態作用域所以它在定義的時候我在寫這個 function 的時候它就已經把 x 已經說好這裡面沒有 那找外面就直接找到外面這裡所以在用的時候它都不太會變這是這一張要講的事情那我們跑跑看我們有一個 var x我直接用英文 out 好不好然後我們有然後這邊有 console.log x然後我們在functionto然後這邊我們會去定義一個 var x等於int然後我們在這邊會去執行 function 1a function 1然後在外面還要執行什麼執行 function 2因為你這邊定義完了以後你要執行它嘛對不對好這時候呢你看我們已經我們這邊定義兩個 function 對不對在這邊才去執行 function 2ok那這邊在定義的時候它就已經去找到這個 x它在定義這個變數在定義這個 function 的時候已經把這個 x 已經找到外面的這個 x所以它會找到 out 這個字而不是像動態定義如果是動態作用域的話它才是就是在執行的時候才去找所以大家要記得就是Javascript 在定義的時候它就會先把這個 x 先找好ok所以這個 x 就不會影響這個在執行的狀況好的我們講痊癒變數我們在第二我們在很前面的時候已經有提過痊癒變數那痊癒變數呢就是在講說在整個 document 就是整個 document 就是對於Javascript來講就是一個痊癒那如果沒有用 var 宣告的話那它自動就會長在 document 下面就是一個痊癒的屬性好的那在 Javascript 裡面最上層的東西是 windowok所以在 window 下面就是痊癒變數都會依附在 window 底下好的那變數Javascript 裡面變數宣告以後就有不可刪除的特性那有已宣告的變數是痊癒物件裡的一個不可變更的屬性那你也可以用函式去改變痊癒變數的值好的如果我們有一些變數是宣告在function 裡面的那我們在外面我們是讀不到這裡面的因為它的作用域我們也有提到嘛var 的作用域在哪裡var 的作用域是不是在 function 就會就是外面會讀不到因為它的作用域只有在單獨的那個 function 裡面比如說像這個 inner這個 inner 其實就是區域變數它只有在 var inner 這裡面這個 function它的 inner 值才是 inner那在外面你去找 inner 這個變數它會跟你講說欸 it’s not defined你根本沒有你根本沒有跟我講有 inner 這個變數啊可是在這個 function 裡面inner 就是有用到 inner所以這個 inner 的作用域只有在這一個 function 裡面OK那像這一個 get global的這個 a這個 a 它會先找這一個 function 的作用域它找欸 它沒有這個區域變數 a所以它會找外面它會發現這個全域變數OK 那我們跑一下欸 我這一段 code 是不是要放在我還是 我放上去好了是不是好 首先我們有一個變數全域變數叫做 a然後它的值是 global好 然後我們有一個 function然後它的它的名字是 get global在這裡面呢它會 console.log 一個 a然後呢 在這邊我們會去執行這個程式對不對 執行這個 function就是我們去 call 這個 functiongetglobal好 這時候它 get它去 call 這個 function 的時候這個 a 它在裡面沒有區域變數所以它直接全域變數 a 就直接 call 出來好的那如果說像這個例子我們有一個 function 叫做 var inner對不對然後 var inner 裡面有一個var inner對不對然後呢 它叫做 inner它裡面是字串然後這個字串裡面是 inner好那我們建好這個 var inner 以後呢就算我們有去執行它我們有執行它我們有執行它我們在外面叫 inner 的時候我們還是找不到這個東西ok因為這個 inner 只有在function 裡面才這個 inner 才會有作用可是你在外面你根本就沒有叫過這個東西所以外面是讀不到裡面因為作用域的關係好的這是十三之一