# var, let and const ## Scope 作用域 >Scope determines the accessibility (visibility) of variables. Scope 定義了變數的可及與可視範圍。(W3C) #### 作用域分為兩種: - **Global Scope 全域作用域** > 即不在函式或區塊內宣告的變數,可以在任何地方取用變數的範圍。 ```javascript= // 用var宣告的全域變數 var myName = "Tommy"; function hello(){ console.log("Hello",myName) //Hello Tommy } hello() // 注意: 未指定宣告的變數,即使是在函式內,也會成為全域變數。 function hello(){ myName = "Tommy"; } hello() console.log("Hello",myName) //Hello Tommy ``` - **Local Scope 區域作用域** > 宣告的變數需在特定範圍內才可以取用。 #### 區域作用域又可以分為兩種: - **==Function Scope 函式作用域 (var)==** > - 在函式內宣告的變數,僅在函式內可取用。 > - 區塊(for, while)變數會污染(覆蓋)全域變數。(解決:閉包&IIFE) ![](https://i.imgur.com/FBp3Hso.png) // a is not defined - **==Block Scope 區塊作用域 (let const)==** > - 在區塊(大括號)內宣告的變數,僅在區塊內可取用。 > - ES6 提出新的宣告方式let, const,宣告的變數為區塊作用域。 > - 兩者差異在於 const 宣告的值不可變動(常數)。 :::warning **當 const 宣告的值為陣列或物件時:** 由於陣列和物件的操作都是屬於 reference type ,當變數成立時,變數的內容是指向記憶體某一個位置的。也就是定義了一個常數陣列之後,如果再 push 新的資料進去是可以執行的,因為指標並沒有指向另一個記憶體位置。 ::: ```javascript= const arr = [1, 2]; arr.push(3); // [1, 2, 3] console.log(arr); const obj = {name: 'Johnson'}; obj.url = 'https://blog.johnsonlu.org'; // { name: 'Johnson', url: 'https://blog.johnsonlu.org' } console.log(obj); ``` ## 補充: Scope Chain 作用域鏈 > - 不同執行環境的變項不會互相影響。 > - 每個執行環境都會有一個參考的外部環境(Outer Environment),外部環境取決於程式碼撰寫的位置(Lexical Environments)。而執行環境與外部環境的串接就叫做 Scope Chain。 - **Outer Environment 外部環境參考** - **Lexical Environment 詞彙環境**(開發環境中的程式位置) :::info 在程式的世界中,Scope 可以分為兩種,分別是: - **[Lexical Scope 語彙作用域](https://ithelp.ithome.com.tw/articles/10194745)**(JS與大多數的語言皆是採用這個!)(簡單說就是內層區塊可以取用外層變數,但外層不能去用內層的) - Dynamic Scope 動態作用域(指的是在執行程式碼的時候才會去界定作用域) ::: ![](https://i.imgur.com/t4ZOoaC.png) ![](https://i.imgur.com/mltie3c.png) #### Hi 題目: ```javascript= var name = "AMO" function a(){ var name="BMO" b() } function b(){ console.log(name) } a() //AMO // 如果function b 換個位置寫 var name = "AMO" function a(){ var name="BMO" function b(){ console.log(name) } b() } a() //BMO ``` #### 比較 | | var | let | const | | -------- | -------- | -------- | -------- | | Scope | Function | Block | Block | | 宣告的值 | 變數 | 變數 | 常數 | | 重複宣告 | O | X | X | #### 參考資料: https://blog.johnsonlu.org/%E7%94%A8-let%E3%80%81const-%E5%8F%96%E4%BB%A3-var/ https://pjchender.blogspot.com/2015/12/javascriptscope-chainouter-environment.html https://medium.com/itsems-frontend/javascript-scope-and-scope-chain-ca17a1068c96 https://medium.com/summers-life/javascript-execution-contexts-c0bfed316fe0