Karen Huang
4 min readOct 13, 2021

ㄟ問你喔,var, let 和 const 有啥不同?之一 (變數與作用域)

Photo by travelnow.or.crylater on Unsplash

在探討這三者的差異之前,應該要先來談一下,var, let, 和 const 的用途:

當需要電腦協助儲存一筆資料到記憶體的時候,要透過 var, let 或 const 來宣告 (declare) 變數,將資料存到變數裡,變數則會儲存在電腦記憶體,往後再呼叫這個變數,便能拿到這筆資料。

假設要告訴電腦,Karen 有 1 杯茶,Roger 有 3 杯茶,可以怎麼敘述呢?

let karenHasTea = 1; let rogerHasTea = 3;

透過 let 就是在宣告 karenHasTea (變數),並賦予變數的值為 1。

註:這邊的等號是賦值運算子的一種。

而當一個變數被宣告的同時,也會有一個作用域跟著這個變數,於是你可能又想問,什麼是「作用域 (variable scope) 」?

簡單來說,作用域就是一個變數能夠被存取到的範圍,而這範圍又分為全域作用域區域作用域

但是,全域作用域和區域作用域,到底又代表什麼意思呢?我們應該如何理解這兩種區域作用域的範圍?

全域作用域 (Global Scope)

前面提到,我們透過 var, let 或 const 來宣告一個變數,但是假如不透過它們「宣告」變數,直接對變數賦予一個值,這是可以的嗎?

(是的,記者現在實地為您測試…)

假設今天有一個變數為 myName,我賦予它一個值 ‘Karen’:

myName = 'Karen';

然後我再度到 chrome 的 dev tool 呼叫 myName 這個變數,主控台顯示:

由此可知,不透過 var, let 或 const 來宣告,myName 也是可以寫入資料的,只是這時沒有被宣告,它存在的範圍會是在「全域作用域」,既無法確認它來自哪裡,它可以被存取的範圍也有模糊不清的問題(後續將會舉例說明),未被宣告過的 myName 是一個「全域屬性」,為避免發生遺憾…,

請一定要記得宣告你的變數!

宣告變數,像是這樣:

let myName = 'Karen';

被宣告過的變數,可以想像成是在幫一個變數劃出存取範圍。當變數是在函式之外被宣告,它的作用範圍就是屬於全域作用域;相反地,在函式之內被宣告的變數,它的存取範圍就是在區域作用域,而區域作用域又可分為函式作用域區塊作用域

那你可能又會想問,為什麼區域作用域內,又要再分函式作用域區塊作用域

以下將開始說明。

前情提要:在 JavaScript ES6 出現之前,沒有 let 和 const,只能靠 var 來宣告變數,而 var 宣告的變數就是在「函式作用域」,直到 ES6 之後有了 let 和 const,「區塊作用域」才應運而生。所以,函式作用域是什麼?它和區塊作用域又有何差別?

區域作用域 (Local Scope)

首先,要先來解釋何謂區域作用域?

簡單來說,區域作用域是相對於全域作用域的概念,只要不是在全域的範圍內的,都是屬於區域作用域,像是 function 函式、if 判斷式、for 和 else 的迴圈內的範圍,都是屬於區域作用域,而 JavaScript 的區域作用域又可分為函式作用域與區塊作用域。

函式作用域 (Function Scope)

函式作用域的範圍是在函式之內。

為何函式外的 console.log 會印出 not defined 呢?

因為 myFavoriteSingerLately 這個變數在函式內被宣告後,它的作用域僅限於函式內,在函式外的地方就讀取不到這個變數。

註:undefined 與 is not defined 是不同的,not defined 所指的是這個變數在這個區域是不存在的,根本讀取不到;undefined 則是指出在記憶體中有這一筆變數資料,只是尚未被賦予值。

區塊作用域 (Block Scope)

區塊作用域的範圍是在大括號 { } 之內。

為什麼在大括號外的 console.log 會印出 not defined 呢?

因為 myFavoriteSingerLately 這個變數在大括號內被宣告後,它的作用域僅限於大括號內,在大括號以外的地方就讀取不到這個變數。

透過以 let 宣告變數在函式作用域與區塊作用域的例子,解釋了這兩個作用域的涵蓋範圍。在理解了這兩種作用域的範圍後,將在下一篇更進一步探討,var 和 let 的差異。

Karen Huang
Karen Huang

Written by Karen Huang

寫下來的,比較不容易忘記。

No responses yet