iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
2

變數(variable)

https://ithelp.ithome.com.tw/upload/images/20200923/20119062ewmvmQX8PU.jpg

cover picture sponsor: gleammming.art

在開發程式的過程中,我們時常會需要處理資料的問題,而整個存取資料的過程就好像倉儲業者一樣:

司機:「我這邊有一個東西要送到市政府,便條紙上說代號是 富士山,我需要裡面的東西。」

配送員:「好喔!我找一下,代號叫做 富士山 是吧?我查一下它的位置……它的位置是 021。」

接著配送員走進倉庫編號 021 的位置並打開了箱子,裡面是一個蘋果。

配送員:「給你,裡面是一個蘋果!」

司機:「好的,那我要出發了!」


宣告變數

在 JavaScript 中,我們可以透過 var 關鍵字來宣告一個變數:

var box;

接著在程式執行期的創造階段時,解析器會透過一張記著識別字的大表,來確認先前有沒有同樣的識別字:

https://ithelp.ithome.com.tw/upload/images/20200923/20119062DR9HbQebj8.png

如果之前還沒宣告過,那麼解析器就會接著將識別字 box 所存的地址 指向 一個沒用過的記憶體地址(例如:0x00)給這個識別字,並且初始化一個值 undefined

https://ithelp.ithome.com.tw/upload/images/20200923/20119062G0p0GGuSK0.png

如果已經使用 var 宣告過的話,那麼他將不會影響原有的記憶體位置。

但如果你是使用 ES6 中的 const 重複宣告變數的話,引擎會提示你該變數已經被宣告過了。


藉由變數儲存資料

在宣告完變數後,接下來如果你想要透過變數儲存資料的話,我們可以藉由 = 賦值運算符(Assignment Operator) 來幫我們達成:

var box = 'Gorilla!';

「但是……那不是等號嗎?」

抱持著數學家的眼光,你可能會感到疑惑。但我很遺憾且必須鄭重的告訴你說:「那不是等號,千萬不要這樣理解。」因為 = 這個符號在程式語言中多半是 「賦予某個值」 的概念。

而回到上方的程式碼中,一開始我們如同宣告變數時的規則,一樣會先分配好一個記憶體:

https://ithelp.ithome.com.tw/upload/images/20200923/20119062n3FwKN8YRw.png

在初始化完畢後,接著解析器才會幫我們做後續賦值的行為,而當解析器在賦值時,它會 重新分配 一個新的記憶體地址並將值放入其中,再將變數原先指向 0x00 的指標改為指向 0x01

https://ithelp.ithome.com.tw/upload/images/20200923/201190624xgCeGChOg.png

如果後續又有重新賦值的行為的話,就會如上方流程一樣再重新分配一個新的記憶體地址給它。

某個記憶體地址沒有被任何變數所參考到的話,在瀏覽器上會自動被記憶體垃圾回收機制所自動處理掉,所以你可以不用擔心 0x00 將來的處置。(詳見後續的 垃圾回收機制 章節)

若是直接將值賦值給變數皆會重新分配記憶體地址,倘若是透過 變數賦值給另一個變數 時則會有另一個機制處理,詳見資料型別章節。


藉由變數取得資料

現在我們會宣告變數也會儲存值進去了,如果你想要找回這個資料,你可以透過 變數名稱 再次尋找到它:

var box;
console.log(box); // undefined

在上面程式碼中的第二行中,解析器會先去表中尋找 box 所指向的記憶體位置,並回傳指向記憶體地址中的值。

https://ithelp.ithome.com.tw/upload/images/20200923/20119062Wj8vcOsRdO.png

而這時我們可以透過 console.log(放入你想印出的值),將值印到瀏覽器中的開發者工具列上。

https://ithelp.ithome.com.tw/upload/images/20200923/20119062tSqvGNkXzt.jpg

另外,倘若試著取得未宣告的變數時,引擎會拋出一個錯誤來提示你:

anotherBox; // Uncaught ReferenceError: anotherBox is not defined

找址(LHS)與找值(RHS)

在數學領域中 LHS 意思即為等號的左邊(Left Hand Side),RHF 則為等號的右邊(Right Hand Side);而對於 JavaScript 來說就如同 找址找值

現在我們已經會宣告變數、儲存資料與讀取資料了,而在 JavaScript 當中,懂得區分什麼時候是 找址,什麼時候是 找值 是一件很重要的事情,我們用一個簡單的例子來舉例:

var box = 1;
console.log(box)

在第一行中 box = 1box 主要用意是為了找到 box 的所指的 記憶體位置,並把 1 放進去,也就是說 LHS 關注的是該變數所指的是 哪個記憶體

而第二行 console.log(box) 中的 box 是為了找到其記憶體中的 ,並把它顯示出來,也就是說 RHS 關注的是該變數所指的記憶體中的 值是什麼

接下來的幾個章節中陸陸續續會再次遇到 找址找值 的議題,若你閱讀到後面忘記時,不彷回來再看看這兩者的差別。


延伸閱讀:變數命名(一)

有關於變數的命名可以參考下列兩個基本指標:

  • 命名規範
  • 命名規格

命名規範

  • 可使用英文、下底線 _ 、錢字號 $與數字等等來替變數命名
  • 不能使用數字開頭的名稱
  • 不能使用關鍵字、保留字,避免語法解析時會解析錯誤(如:var)。
  • 大小寫會視為不同的變數。(如:boxBOX

命名風格

命名風格的部分有以下幾種:

  • 小駝峰式(lower camel case)
var firstName;
var lastName;
  • 大駝峰式(upper camel case)
var FirstName;
var LastName;
  • 蛇形命名法(snake case)
var first_name;
var last_name;

至於選用哪種,請依照團隊的開發習慣作為考量;最後,還有另一種比較特別的是全大寫心法:

var PI = 3.1415926;

這種命名方法通常出現在常量的數值,也就是一個固定值,也就是說我們平常不會去更動它的值,主要是為了取這個值來進行運算,而透過這樣的命名心法我們會自然而然的不會去任意的更動它!(當然,你也可以使用 ES6 中的 const 來宣告常數)。

以上的的命名規範與命名風格只能算是基礎該做的,而接下來往後幾個章節會陸陸續續會再強化這一塊的概念!


建立模型時間

目標:瞭解變數存取值的機制。

整理重點:

  • 分配記憶體這件事情在 JavaScript 中並不能自己決定,我們能對變數做的事情就是 取值賦值
  • 對於變數來說,有的時候我們使用是為了找址(LHS),有時候是為了找值(RHS)。

認知模型樹狀圖參考:

請試著透過這張樹狀圖或你自製的圖表回想這章節的概念:

  • JavaScript
    • 變數
      • 宣告
        • 重複宣告
      • 賦值
        • 重複賦值
      • 取值
      • 命名
        • 規範
        • 風格

為了能夠更輕易瞭解變數的存取上面的記憶體模型有經過簡化。


上一篇
【建立模型】2-1 瀏覽器是如何看懂我寫的程式?
下一篇
【建立模型】2-3 資料型別(data types)之間的差異
系列文
《透過認知心理學認識 JavaScript》貓咪也能輕鬆學習的 JavaScript33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言