前言
在程式語言中,變數是用來操作資料的語法特性。本文介紹 JavaScript 中和變數相關的議題。
多種宣告變數的方式
在 JavaScript 中,有三種宣告變數的方式:
var
let
(ES6+)const
(ES6+)
在 ES5 (含) 以前,宣告變數的保留字只有 var
,而沒有宣告常數的方式。但 var
在語法特性上有許多缺陷,像是重定義及可視域等。所以後來新增 let
及 const
。
let
基本上就是要取代 var
的,因 let
和 var
的功能重疊,但前者改良了後者在重定義及可視域上的缺點。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 目前的保留字,這裡則列出未來可能會用到的保留字。
保留字不用刻意去記,因為學習程式的過程中自然會用到這些語法,而且編輯器都會幫我們用語法高亮標示出來。
var
和 let
的差異
在本文的尾段,來談一下 var
和 let
的差異。
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 自動轉換程式碼。