# var 跟全域與區域變數的關係 <div class="block"> **本篇會談到** - 區域變數 local variable - 全域變數 global variable - var 的作用域 - var 與 for 迴圈 </div> ## 全域變數 & 區域變數 JavaScript 在查找變數時,會循著作用域鏈 (scope chain) 一層一層往外找,直到找到宣告的變數或找不到變數 (undefined) <br> ## ✐ 區域變數 local variable 區域範疇(Local scope) - function 內宣告變數,當 function 執行完畢之後會全部消失(當下執行時,值是存在的) - 好處:可以釋放記憶體 ```javascript= function count(one, two){ let total = one + two; console.log(total); // 在這邊印出 18 } count(8,10); console.log(total); // total is not defined // total 會在 function 完成當下就消失 // 會看到值是因為第四行執行當下還存在 ``` <br> <br> ## ✐ 全域變數 global variable 全域範疇(Global scope) - 在外面撈出 function 內的值:會在 function 內尋找有沒有宣告,如果沒有就會往外找 - 瀏覽器下的全域物件是 window - functio 外宣告的變數具有全域性 ```javascript= let total; function count(one, two){ total = one + two; // total 賦予 one + two // 此時在 function 外面呼叫就會成功 } count(8,10); console.log(total); // 18 ``` ### 全域、污染 - 沒有宣告成變數,成為全域屬性時: ```javascript= a = 0; function fn() { a = 1; } fn() console.log(a) // 上方結果為 1 因為他們沒有被宣告成變數 兩個就都是全域屬性 ``` - [屬性可以被刪除](https://hackmd.io/@unayojanni/HyzWz9R0u/%2FsmF8tcU5SRGvzmZsK0VTUw#➤-物件刪除物件屬性https://): ```javascript= a = 0; console.log(a); // 輸出 0 console.log(window); // 全域物件 且裡面會有 a 屬性 delete window.a // 用 delete 刪除屬性 a console.log(a); // 輸出 a is not defined console.log(window); // 全域物件的 a 也不見了 ``` - 變數無法被刪除: ```javascript= var b = 1; console.log(window) // 全域物件 且裡面有 b delete window.b // 刪除屬性在這裡不起作用了 因為 b 是變數不是屬性了 console.log(window); // 所以這裡 b 還是存在 console.log(b); // 可以輸出 1 ``` ## ✐ var 的作用域 1. {} 是一個 block,var 的作用域沒有作用,所以可以取到外面的值 ```javascript= { var b = 2; } console.log(b); // 2 // {} 是一個 block,沒任何作用,就只是一個 block,先說明程式碼可以這樣寫不會報錯 // 然後在 block 裡面用 var 宣告變數 b,在 block 外也可以獲取到這個變數 b ``` 2. 利用 degubber 查詢 Scope(作用域)裡面Local 有什麼 ```javascript= function fn() { var a = 1; debugger; // 這個可以讓程式碼停在這一行 並開啟 Sources 功能 // 此時可以看到右邊的 Scope(作用域)裡面有一個 Local 就是他目前的函式中有哪些東西 } fn(); ``` ##  3. 全域跟函式中各自宣告 a,兩者不會互相影響 ```javascript= var a = 0; function fn() { var a = 1; console.log('local', a) // 1 } fn(); console.log('全', a) // 0 ``` 4. 若函式中沒有宣告 a ,此時 a 會向外查找變成全域變數,更改函式中的 a 值,會連帶更改全域的 a ```javascript= var a = 0; function fn() { a = 1; } fn(); console.log('全', a) // 1,在函式中 全域的值被改變了 ``` 5. var 的辭法作用域 - var 作用域在程式碼寫完的當下就確定,不需要執行代碼後才去找 ```javascript= var a = 0; function fnA() { console.log(a); } function fnB() { var a = 1; } fnB(); // 他有自己的作用域在函式裡面,所以不會影響到全域 fnA(); // 這裡就很清楚,輸出結果是全域的 0 ``` - 進階題 ★★★★★ ```javascript= var a = 0; function fnA() { console.log(a); } function fnB() { var a = 1; fnA(); // 不需要看在哪調用 fnA() 去決定 a 值 // 而是看 fnA() 被創建在哪、函式中是否有宣告 a } fnB(); // 沒有就找 function fnA() {...} 的外層 // 所以上面這題就指向全域的 a,輸出為 0 ``` 6. var 重複宣告也不會報錯 ```javascript= function fn() { var a = 1; var a = 0; console.log(a) } fn(); // 0 // a 作用域只在函式裡 ``` ## ✐ var 與 for 迴圈 - 滿足條件會出現在迴圈內 - 不是條件的值,會跳出迴圈外 ```javascript= for (var i = 0; i < 10; i++) { console.log(i); // 這裡會輸出 0~9 // 一直累加到最後 10 會跳出 } console.log(i); // 10 // 因為 i 超過 9 才會跳出 for 迴圈 ``` - for迴圈 + [setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) - setTimeout 屬於非同步行為,可以直接把他往後放,所以會取到最終的結果 ```javascript= for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i); // 10 }, 0); } // 輸出 10 因為 setTimeout 屬於非同步行為 // JS 默認在所有事件結束後才會執行非同步行為 // 所以執行 setTimeout 時 i 已經跳出 for 了 ``` ## ✐ 提升(hoisting) - 在初始化時,嘗試去取出值,稱為空值 - 因為用var宣告的變數會發生提升(hoisting),所以程式碼會被拆解,var a這行會被置頂,最後以下述的方式執行。 ```javascript= console.log(a); // hoising var a =1; console.log(a); // 1 ``` ###### tags: `JS` {%hackmd @unayojanni/H1Qq0uKkK %}
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up