美思 現代 [JavaScript] 程式設計教學:宣告和使用變數 (Variable)

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

在程式語言中,變數是用來操作資料的語法特性。本文介紹 JavaScript 中和變數相關的議題。

多種宣告變數的方式

在 JavaScript 中,有三種宣告變數的方式:

  • var
  • let (ES6+)
  • const (ES6+)

在 ES5 (含) 以前,宣告變數的保留字只有 var,而沒有宣告常數的方式。但 var 在語法特性上有許多缺陷,像是重定義及可視域等。所以後來新增 letconst

let 基本上就是要取代 var 的,因 letvar 的功能重疊,但前者改良了後者在重定義及可視域上的缺點。JavaScript 保留 var 的目的僅是為了相容於現有的程式。如果有在用 TypeScript 或 Babel 轉換 JavaScript 程式碼的話,建議一律改用 let,不要用 var

以下是命名變數的程式碼片段:

/* Home-made assertion. */
function assert(cond, msg) {
  if (!(cond)) {
    throw (msg ? msg : 'Assertion failed');
  }
}

let object = 'World';
assert(`Hello ${object}` === 'Hello World');

const 則是用來命名常數,以避免程式設計者無意間修改到常數。在適常的時機,建議用 const 取代 var

以下是命名常數的程式碼片段:

const PI = 3.1415927;

由於 Math 物件已經有 Math.PI 常數了,此程式碼片段僅是展示 const 的用法。

命名識別字 (Identifier) 的規範

在電腦程式中,識別字是具有特定意義的符號。識別字可能代表變數、函式、物件等。除了程式語言原有的識別字外,程式設計者可以以合乎程式語言規範的方式建立新的識別字。

JavaScript 命名識別字的規則如下:

  • 首字為萬國碼字母、$ (錢字號)、_ (底線)
  • 之後為萬國碼字母、$_、阿拉伯數字

雖然 JavaScript 允許用萬國碼命名識別字,實務上程式設計者只會用英文字母。這是為了要讓不同國家或地區的程式設計者能夠合作的考量。

在 JavaScript 中使用 $ 命名識別字的例子很少。比較知名的例子是 jQuery 用 $ 做為其函式庫的前綴。

首字使用 _ 的例子也很少。實際上不建議用 _ 做為識別字的首字,因為少數內建變數會用 _ 開頭。少數例外是 Underscore.js,該函式庫以 _ 做為其函式庫的前綴。

除了合乎命名規範外,最好要用一致的命名風格。詳見下一節的內容。

命名識別字的風格

常見的識別字命名風格如下:

  • PascalCase
  • camelCase
  • snake_case
  • kebab-case (JavaScript 中無法使用)
  • ALL_CAPS_CASE

由於 JavaScript 在程式碼上刻意向 Java 靠攏,最常用的風格也是前兩者。PascalCase 用來命名類別 (class),camelCase 則用來命名變數、函式 (function)、方法 (method) 等。

ALL_CAPS_CASE 只用來命名常數。snake_case 在 JavaScript 中較少使用。

保留字 (Keyword)

保留字是程式語言中內建的語法,不能重用來命名識別字。這裡列出 JavaScript 目前的保留字,這裡則列出未來可能會用到的保留字。

保留字不用刻意去記,因為學習程式的過程中自然會用到這些語法,而且編輯器都會幫我們用語法高亮標示出來。

varlet 的差異

在本文的尾段,來談一下 varlet 的差異。

var 是函式可視 (function-scoped)。除了包在函式以外,頂層的 var 變數是全域可視。此外,重定義也不會發出警告。在工程性上,var 的設計很差,所以後來才會出現 let

相對來說,let 是區塊可視 (block-scoped),這比較接近主流語言的習慣。此外,重定義 let 變數時會引發錯誤。

以下是合法但不合理的 JavaScript 程式碼片段:

/* Home-made assertion. */
function assert(cond, msg) {
  if (!(cond)) {
    throw (msg ? msg : 'Assertion failed');
  }
}

/* Run a dummy for loop. */
for (var i = 0; i < 10; ++i) {}

/* Wrongly correct. */
assert(10 === i);

改用 let 後變數的特性會比較接近主流語言:

/* Home-made assertion. */
function assert(cond, msg) {
  if (!(cond)) {
    throw (msg ? msg : 'Assertion failed');
  }
}

/* Run a dummy for loop. */
for (let i = 0; i < 10; ++i) {}

assert('undefined' === typeof i);

如果一定要用 ES5 版本的 JavaScript,要自行用 IIFE 模式把 for 迴圈包起來:

/* Home-made assertion. */
function assert(cond, msg) {
  if (!(cond)) {
    throw (msg ? msg : 'Assertion failed');
  }
}

(function () {
  for (var i = 0; i < 10; ++i) {
    /* Run some code here. */
  }
})();

assert('undefined' === typeof i);

手動寫這種程式碼太不方便了,還是建議用 TypeScript 或 Babel 自動轉換程式碼。

關於作者

身為資訊領域碩士,美思認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

美思喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,美思將所學寫成文章,放在這個網站上和大家分享。