📓
Something About JavaScript
  • Introduction
  • Day 1:前言
  • Day 2:資料型態的夢魘——動態型別加弱型別(1)
  • Day 3:資料型態的夢魘——動態型別加弱型別(2)
  • Day 4:動態型別加弱型別不是罪——怎麼 JavaScript 一摔就變成個印度阿三?
  • Day 5:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (1)
  • Day 6:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (2)
  • Day 7:傳統 var 關鍵字的不足
  • Day 8:var 掰掰 —— ES6 更嚴謹安全的 let 和 const
  • Day 9:圖解變數作用域(Scope)
  • Day 10:程式也懂電梯向上? —— Hoisting
  • Day 11:Strict Mode (嚴謹模式)
  • Day 12:看 Strict Mode 如何施展「還我漂亮拳」(1)
  • Day 13:看 Strict Mode 如何施展「還我漂亮拳」(2)
  • Day 14:來挖挖恐龍骨 —— with 語法
  • Day 15:this 關鍵字 (1)
  • Day 16:this 關鍵字 (2)
  • Day 17:this 關鍵字 (3)
  • Day 18:this 關鍵字 (4)
  • Day 19:函數定義 (Function Definition) 的 100 種寫法
  • Day 20:ES6 的箭頭函數 (Arrow Functions)
  • Day 21:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (1)
  • Day 22:箭頭函數 (Arrow Functions) 的 this 和你想的不一樣 (2)
  • Day 23:ES6 物件實字威力加強版 (Enhanced Object Literals)
  • Day 24:函數呼叫 (Function Invocation) 與立即函數 (Self-Invoking Functions)
  • Day 25:不是多了塊魚 —— 立即函數的應用整理
  • Day 26:程式界的哈姆雷特 —— Pass by value, or Pass by reference?
  • Day 27:別管變數 Pass by Whatever,尋找容易理解的銀色子彈 (Silver Bullet)
  • Day 28:閉包 (Closures)
  • Day 29:閉包 (Closures) 進階打怪實戰
  • Day 30:ES10 醞釀中 —— 擁抱 JS の 未來
Powered by GitBook
On this page
  • 學程式很重要的一點是要思考「為什麼」
  • 傳統 var 的變數宣告方法
  • 傳統 var 有什麼缺點?
  • 語法允許重複宣告 (Re-Declaring)
  • 不支援區塊作用域 (Block Scope)
  • 不支援常數 (Constant) 特性
  • 總結
  • Referneces

Was this helpful?

Day 7:傳統 var 關鍵字的不足

PreviousDay 6:湯姆克魯斯與唐家霸王槍——變數的作用域(Scope) (2)NextDay 8:var 掰掰 —— ES6 更嚴謹安全的 let 和 const

Last updated 4 years ago

Was this helpful?

長久以來 JavaScript 宣告變數所用的關鍵字 (Keyword) 都是 var。

大家已經非常習慣,甚至在 let 和 const 導入這麼久之後,仍時常看到 var 的芳蹤。(當然一部份原因跟 ES6 支援度的普及有關係)

但傳統 var 有幾個缺點,容易造成程式編寫上的不嚴謹,進而導致變數控管困擾。

ES6 導入了新的宣告關鍵字—— let 和 const,有助於改善原本 var 不嚴謹的缺點,進而增加新的特性,例如 Day5、Day6 文章提到的舞棍阿伯……不對,是 Block Scope。

在介紹 let 和 const 之前,我們要先了解傳統 var 有什麼缺點。

學程式很重要的一點是要思考「為什麼」

程式語言的變革非常快,不同語言間時常會互抄,我是說,互相學習。

各家語言的主事者不斷推出新版本,例如常聽到的 C# 4.0、Java 9、PHP 7,就是為了不斷導入新特性或修正原先的設計缺失,讓自家語言的功能更加豐富和周全。

而這些新特性的導入往往都有其歷史原因或背後考量,不會是突然間靈光一閃,上帝啟示。

(Source: )

如果只知其然而不知其所以然,只是去背用法,但不知道為什麼需要這樣用,不僅無法融會貫通,在運用上也不容易到位。

因此在介紹 let 和 const 之前,我們要先了解傳統 var 有什麼缺點,才能理解為什麼需要導入 let 和 const,對程式又能有什麼幫助。

傳統 var 的變數宣告方法

傳統 var 宣告變數的語法如下:

var gameName = "IT Help 2019";
var gamer = "OneJar", topic = "Something about JavaScript", progress = 7;
var isFinished; // A variable declared without a value will have the value **undefined**.

作者閒聊:希望 isFinished 能順利被賦值(遠目)

要點懶人包:

  • 使用 var 關鍵字來宣告變數。

  • 可只用一次 var 一次宣告多個變數,用逗號 (,) 區隔。

  • 宣告的同時可進行初始化,也就是賦值。

  • 若沒有初始化,則預設值會是 undefined。

以上沒什麼問題。

但 var 有 3 個缺點,或稱為不足之處。

傳統 var 有什麼缺點?

語法允許重複宣告 (Re-Declaring)

例如以下例子:

console.log(x);     // ReferenceError: x is not defined (註)
var x;
console.log(x);     // undefined
x = 123;
console.log(x);     // 123
var x;
console.log(x);     // 123

註:以上這段程式如果完整執行,第一個 console.log(x); 實際上會印出 undefined 而不是 Error,因為變數宣告有 Hoisting 效果。關於 Hoisting ,預計後續的文章再作詳細介紹,本篇先單純關注 var 的問題。

即使在同一個作用域,同樣名稱的變數也允許重複宣告,不會跳出任何錯誤或警告,很容易忽略自己曾宣告過。

值得注意的是,重複宣告一個變數,並不會重置該變數的值。

一段很長的程式,我們可能不記得前面宣告過同名的變數,後面再次宣告時往往當成第一次宣告,容易疏忽造成小 Bug。

例如以下的情境:

var name = 'OneJar';
.........
.........
.........
var name;
while(true){
    if( name === undefined ){
         console.log('The first time to execute.');
    }
    ............
}

允許重複宣告不僅沒有用處,還容易造成問題。

一個較好且普遍的程式編寫習慣:將需要宣告的變數集中在該作用域的一開始,並賦予初始值。

不支援區塊作用域 (Block Scope)

例如我們在 Day6 舉的例子:

function myFunc(){
    {
       var n1 = "OneJar";
    }
    console.log("myFunc(): n1=", n1);
}

myFunc();

執行結果:

myFunc(): n1= OneJar

用 var 宣告的變數並不具 Block Scope 效果。

而 Block Scope 特性在其他程式語言很常見,其他語言開發者轉到 JavaScript 時如果沒注意到這一點,容易造成變數管理上的漏洞。

不支援常數 (Constant) 特性

常數 (Constant) 指的是「固定不變的數值」。

在程式裡常需要宣告一些變數,但變數裡的值只需要作一次初始化,不需要也不希望在程式執行過程被更改,也就是我們希望這類變數具有常數性質。

例如數學的 PI 是 3.14,如果在程式某個小角落被誤改,就會造成整體運算結果的錯誤。

var PI = 3.14;
PI = 1234;

但傳統的 var 無法做到這項控管,你想怎麼改變值都可以,對整體程式來說就造成風險。

許多其他程式語言對於常數性質的變數都有提供控管機制來提高安全性,一旦誤改,可能編譯階段就能發現,甚至 IDE 在編寫階段就能提醒,減少 Debug 負擔。

例如 Java 使用了 final 關鍵字來保護指定變數不能被更改值:

public static void main(String []args){
    final double PI = 3.14;
    PI = 1234;
}

執行結果:

HelloWorld.java:5: error: cannot assign a value to final variable PI
        PI = 1234;
        ^
1 error

而在 C# 裡是使用 const 關鍵字:

public static void Main()
{
    const double PI = 3.14;
    PI = 1234;  // Compilation error
}

不同語言所使用的關鍵字或語法可能不一樣,但目的都是一致:保護常數性質的變數。

總結

總結用傳統 var 宣告變數的 3 個缺點: 1. 語法允許重複宣告 (Re-Declaring) 2. 不支援區塊作用域 (Block Scope) 3. 不支援常數 (Constant) 特性

以上了解傳統 var 的缺點和限制,下一篇文章就可以來看 ES6 的 let 和 const 如何改善這些不足。

Referneces

W3Schools - JavaScript Variables
網路