# [JavaScript] 範疇(Scope) ###### tags: `前端筆記` ## 總結 1. 範疇決定了變數的「可見度」,變數在哪裡被命名決定我們可以從哪裡讀取該變數 2. 在 JavaScript 中函式及變數「宣告時」就已經決定自己的有效範圍,不是在「叫用」的時候才決定 3. `var` 沒有區塊範疇(block scope),如果把 `var` 放在區塊範疇(block scope)會自動變成全域範疇(global scope) - `let` 及 `const` 則有區塊範疇(block scope) ## 範疇(Scope) 是什麼?  >範疇決定了變數的「可見度」,變數在哪裡被命名決定我們可以從哪裡讀取該變數。 ## 範疇(Scope)有幾種? 1. global scope(全域範疇) 2. local scope(區域範疇) - 因為 ES6 後加入的 `let` 及 `const` 所宣告的變數有效範圍與之前的 `var` 有所不同,所以又可 `local scope` 又可區分為:function scope(函式範疇)及block scope(區塊範疇)兩種 ## Global Scope(全域範疇) 寫在任何函式及花括號({})之外的就算是屬於 global scoep(全域範疇)的變數。 - 任何地方(範疇)都可以讀取改變數 => 甚至在函式裡面 ```javascript= const greeting = 'Hello World!'; function funcA () { console.log(greeting); } funcA(); // Hello World! ``` **函式內沒有使用關鍵字宣告的變數**也會變成全域範疇的變數(所以不要這麼做) ```javascript= function funcA () { greeting = 'Hello World!'; } funcA(); console.log(greeting); // Hello World! ``` ## Local Scope(區域範疇) 宣告在函式裡面及花括號({})裡面的變數就屬於 local scope(區域範疇),因為 `ES6` 加入的 `let` 及 `const` 所以又可以分成 **function scope(函式範疇)及 block scope(區塊範疇)兩種**。 ### 1. Function Scope(函式範疇) 只要在函式內宣告且有關鍵字的變數就屬於 function scope(函式範疇)。 ```javascript= function sayHello () { const greeting = 'Hello World!' console.log(greeting) } sayHello() // 'Hello World!' console.log(greeting) // Uncaught ReferenceError: greeting is not defined // 因為 greeting 係屬函式範疇,出了函式就死了 ``` #### 每個獨立的 Function Scope 沒辦法互相讀取變數 `funcB` 沒辦法讀取 `funcA` 的 `myName`。 ```javascript= function funcA () { const myName = 'lun'; } function funcB () { const myAge = 23; console.log(myName); } funcA(); funcB(); ```  #### 但如果把函式包覆在一起呢? 此時內部的函式範疇可以讀取到外層的函式範疇,但外層沒辦法讀取到內層。 **=> 只能往外找,不能往內找** **=> 這樣子可稱為 Lexical Scope(語彙範疇)或者 Static Scope(靜態範疇)**。 *範例1([ref.](https://ultimatecourses.com/blog/everything-you-wanted-to-know-about-javascript-scope#what-is-scope))* ```javascript= var myFunction = function () { var name = 'Todd'; var myOtherFunction = function () { console.log('My name is ' + name); }; console.log(name); myOtherFunction(); // call function }; myFunction(); // Will then log out: // `Todd` // `My name is Todd` ``` *範例2([ref.](https://css-tricks.com/javascript-scope-closures/))* ```javascript= function outerFunction () { const outer = `I'm the outer function!` function innerFunction() { const inner = `I'm the inner function!` console.log(outer) // I'm the outer function! } console.log(inner) // Error, inner is not defined } ``` *範例3([ref.](https://medium.com/itsems-frontend/javascript-scope-and-scope-chain-ca17a1068c96))* ```javascript= function A() { var varA = 'varA'; function B() { var varB = 'varB'; console.log(varA); console.log(varB); } B(); console.log(varA); console.log(varB); } A(); // varA // varB // varA // Uncaught ReferenceError: varB is not defined => 沒辦法往內找 ``` ### 那什麼是靜態範疇(Static Scope)呢? *範例[ref.](https://blog.techbridge.cc/2018/12/08/javascript-closure/)* 猜看看最後 `echo` 會 console.log 多少出來? ```javascript= var a = 100 function echo() { console.log(a) // 100 or 200? } function test() { var a = 200 echo() } test() ``` 答案是 100。 這就是靜態範疇(static scope)的規則,當變數及函式在「宣告」的時候就已經決定自己的有效範圍,並不是在「叫用」的時候才決定的。 ### 2. Block Scope(區塊範疇) 只要在花括號({})內宣告的變數就屬於 block scope(區塊範疇)。 ```javascript= { const myName = 'lun' console.log(myName); } console.log(myName); ```  - 在花括號({})內**沒有使用**關鍵字就直接宣告變數,該變數會自動變成全域範疇(global scope) ```javascript= { myName = 'lun'; console.log(myName); } console.log(myName); ```  - 而且用 `var` 宣告也會變成全域範疇(global scope),因為 `var` 只支援函式範疇(function scope)而已 ```javascript= { var myName = 'lun'; console.log(myName); } console.log(myName); ```  - 如果在 `if` `for loop` 等屬於區塊範疇(block scope)的地方使用 `var`,那麼該變數也會自動變成全域範疇(global scope) *在 `for loop` 之外可以讀取 i,但讀取不到 x*  *沒有關鍵字當然就會自動變成全域範疇(global scope)*  ## 參考資料 1. 圖片取自 Udemy 課程 [The Web Developer Bootcamp 2021](https://www.udemy.com/course/the-web-developer-bootcamp/) 2. [[JavaScript] Javascript 的作用域 (Scope) 與範圍鏈 (Scope Chain):往外找](https://medium.com/itsems-frontend/javascript-scope-and-scope-chain-ca17a1068c96) 3. [JavaScript Scope and Closures](https://css-tricks.com/javascript-scope-closures/) 4. [JS 原力覺醒 Day04 - Function Scope / Block Scope](https://ithelp.ithome.com.tw/articles/10217481) 5. [所有的函式都是閉包:談 JS 中的作用域與 Closure](https://blog.techbridge.cc/2018/12/08/javascript-closure/)
×
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