Try   HackMD

var 跟全域與區域變數的關係

本篇會談到

  • 區域變數 local variable
  • 全域變數 global variable
  • var 的作用域
  • var 與 for 迴圈

✐ 區域變數 local variable

區域範疇(Local scope)

  • function 內宣告變數,當 function 執行完畢之後會全部消失(當下執行時,值是存在的)

    • 好處:可以釋放記憶體
    ​​​​function count(one, two){ ​​​​ let total = one + two; ​​​​ console.log(total); ​​​​ // 在這邊印出 18 ​​​​} ​​​​count(8,10); ​​​​console.log(total); ​​​​// total is not defined ​​​​// total 會在 function 完成當下就消失 ​​​​// 會看到值是因為第四行執行當下還存在


✐ 全域變數 global variable

全域範疇(Global scope)

  • 在外面撈出 function 內的值:會在 function 內尋找有沒有宣告,如果沒有就會往外找
  • 瀏覽器下的全域物件是 window
  • functio 外宣告的變數具有全域性
    ​​​​let total; ​​​​function count(one, two){ ​​​​ total = one + two; ​​​​ // total 賦予 one + two ​​​​ // 此時在 function 外面呼叫就會成功 ​​​​} ​​​​count(8,10); ​​​​console.log(total); ​​​​// 18

全域、污染

  • 沒有宣告成變數,成為全域屬性時:
    ​​​​a = 0; ​​​​function fn() { ​​​​ a = 1; ​​​​} ​​​​fn() ​​​​console.log(a) ​​​​// 上方結果為 1 因為他們沒有被宣告成變數 兩個就都是全域屬性
    • 屬性可以被刪除
      ​​​​​​​​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 也不見了
    • 變數無法被刪除:
      ​​​​​​​​var b = 1; ​​​​​​​​console.log(window) // 全域物件 且裡面有 b ​​​​​​​​delete window.b // 刪除屬性在這裡不起作用了 因為 b 是變數不是屬性了 ​​​​​​​​console.log(window); // 所以這裡 b 還是存在 ​​​​​​​​console.log(b); // 可以輸出 1

✐ var 的作用域

  1. {} 是一個 block,var 的作用域沒有作用,所以可以取到外面的值
    ​​​​{ ​​​​ var b = 2; ​​​​} ​​​​console.log(b); ​​​​// 2 ​​​​// {} 是一個 block,沒任何作用,就只是一個 block,先說明程式碼可以這樣寫不會報錯 ​​​​// 然後在 block 裡面用 var 宣告變數 b,在 block 外也可以獲取到這個變數 b
  2. 利用 degubber 查詢 Scope(作用域)裡面Local 有什麼
    ​​​​function fn() { ​​​​ var a = 1; ​​​​ debugger; // 這個可以讓程式碼停在這一行 並開啟 Sources 功能 ​​​​ // 此時可以看到右邊的 Scope(作用域)裡面有一個 Local 就是他目前的函式中有哪些東西 ​​​​} ​​​​fn();

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

  3. 全域跟函式中各自宣告 a,兩者不會互相影響
    ​​​​var a = 0; ​​​​function fn() { ​​​​ var a = 1; ​​​​ console.log('local', a) // 1 ​​​​} ​​​​fn(); ​​​​console.log('全', a) // 0
  4. 若函式中沒有宣告 a ,此時 a 會向外查找變成全域變數,更改函式中的 a 值,會連帶更改全域的 a
    ​​​​var a = 0; ​​​​function fn() { ​​​​ a = 1; ​​​​} ​​​​fn(); ​​​​console.log('全', a) ​​​​// 1,在函式中 全域的值被改變了
  5. var 的辭法作用域
    • var 作用域在程式碼寫完的當下就確定,不需要執行代碼後才去找
    ​​​​var a = 0; ​​​​function fnA() { ​​​​ console.log(a); ​​​​} ​​​​function fnB() { ​​​​ var a = 1; ​​​​} ​​​​fnB(); // 他有自己的作用域在函式裡面,所以不會影響到全域 ​​​​fnA(); // 這裡就很清楚,輸出結果是全域的 0
    • 進階題 ★★★★★
    ​​​​​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 重複宣告也不會報錯
function fn() { var a = 1; var a = 0; console.log(a) } fn(); // 0 // a 作用域只在函式裡

✐ var 與 for 迴圈

  • 滿足條件會出現在迴圈內
  • 不是條件的值,會跳出迴圈外
    ​​​​for (var i = 0; i < 10; i++) { ​​​​ console.log(i); ​​​​ // 這裡會輸出 0~9 ​​​​ // 一直累加到最後 10 會跳出 ​​​​} ​​​​console.log(i); ​​​​// 10 ​​​​// 因為 i 超過 9 才會跳出 for 迴圈
  • for迴圈 + setTimeout
    • setTimeout 屬於非同步行為,可以直接把他往後放,所以會取到最終的結果
for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i); // 10 }, 0); } // 輸出 10 因為 setTimeout 屬於非同步行為 // JS 默認在所有事件結束後才會執行非同步行為 // 所以執行 setTimeout 時 i 已經跳出 for 了

✐ 提升(hoisting)

  • 在初始化時,嘗試去取出值,稱為空值
  • 因為用var宣告的變數會發生提升(hoisting),所以程式碼會被拆解,var a這行會被置頂,最後以下述的方式執行。
console.log(a); // hoising var a =1; console.log(a); // 1
tags: JS

最後,親愛的大家!我需要你的大聲鼓勵 ٩(⚙ᴗ⚙)۶

如果覺得這篇文章對你有幫助,請給我個一個小小的鼓勵 ❤ 讓我知道,這會成為我寫下去很大的動力。
對了,我還有其他文章,如果有興趣也來逛逛吧!
(文章中如有覺得不妥之處、錯誤內容,也可以透過聯絡我,我會儘速改善,感謝!)

☞ YoJanni 珍妮 2021 正在設計轉職前端的路上,希望大家在學習的路上能夠一起成長
☞ 聯絡我