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

    前言

    在程式語言中,變數是用來操作資料的語法特性。本文介紹 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 自動轉換程式碼。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
    【追蹤本站】
    Facebook Facebook Twitter Plurk