很久很久以前,在 JavaScript 世界裏,有一個叫變量鎮的地方。這裏住着三兄弟:var、let、const。他們都能“裝東西”,但性格、規矩、出身背景完全不一樣。也正因為這三兄弟的性格差異,程序員江湖裏每天都在上演各種事故現場。

今天,我就帶你走進變量鎮,看看他們各自是怎麼“翻車”的,又該如何正確相處。

老大哥 var:江湖老油條

1、var 關鍵字:最早的居民

var 是 JavaScript 最早的變量聲明方式,堪稱上古神器

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明

在 ES6 之前,整個變量鎮幾乎被 var 一統江湖。但問題也正是從這裏開始的。

2、 var 聲明作用域:沒有塊級概念

在變量鎮裏,var 有個非常“隨意”的性格:它只認函數,不認花括號。

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_作用域_02

很多新手第一次看到這個結果時,內心都是崩潰的:

“不是寫在 if 裏面嗎?怎麼跑出來了?”

在 var 眼裏,if、for、while 都不算地盤,只有函數才算真正的邊界。

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_作用域_03

總結一句話:

var 只有函數作用域,沒有塊級作用域

3、 var 聲明提升:先上車後補票

var 還有一個讓人又愛又恨的能力——聲明提升

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_04

在 JavaScript 引擎眼裏,上面的代碼其實是這樣執行的:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_賦值_05

變量聲明被“偷偷”提到了最前面,但賦值還在原地。這就像你先報了名字進羣,但個人資料還沒填完。

風險點:

  • 不報錯
  • 但結果是 undefined
  • 很容易掩蓋 bug

二哥 let:講規矩的現代青年

後來,ES6 來了,變量鎮迎來了新居民:let

1、let 聲明:有邊界感的人

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_06

let 的出現,第一件事就是:給變量加上邊界感。

2、 暫時性死區:我沒到,你別碰

let 有一個非常重要的概念:暫時性死區(TDZ)

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_賦值_07

直接報錯:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_賦值_08

在 let 看來:“你可以提前知道我會來,但在我真正登場之前,你不能碰我。”

這和 var 的“先聲明後賦值”完全不同。

3、 let 的塊級作用域

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_賦值_09

這一次,變量終於老老實實待在自己的花括號裏

這也是 let 最大的價值之一:減少變量污染,降低心智負擔。

4、 全局聲明:不會掛到 window 上

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_作用域_10

而如果是 var:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_11

這意味着:

  • var 會污染全局對象
  • let 不會

在大型項目裏,這一點尤為重要。

5、 for 循環中的 let:為循環而生

這是 let 最讓人拍手叫好的地方。

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_12

輸出結果:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_13

如果換成 var:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_14

結果是:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_15

原因很簡單:

  • var 只有一個 i
  • let 每次循環都會創建一個新的 i

一句話總結:只要是循環變量,優先 let

三弟 const:外冷內熱的守護者

1、const 聲明:不可變的承諾

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_16

const 的核心思想是:一旦綁定,就不能重新綁定。

但很多人會誤解這一點。

2、const 並不等於“值不可變”

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_賦值_17

真正不能做的是:

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_作用域_18

也就是説:

  • const 鎖的是引用
  • 不是對象內部的屬性

三兄弟性格對比表

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_作用域_19

聲明風格及最佳實踐

講完故事,我們回到現實世界。

1、 不使用 var

這是現代 JavaScript 項目的共識。原因很簡單:

  • 容易產生隱式 bug
  • 作用域不直觀
  • 不符合現代工程化需求

除非你在維護非常古老的代碼,否則:請忘記 var 的存在。

2、 const 優先,let 次之

這是我在團隊裏反覆強調的一條規則。推薦順序:

  1. 能用 const 就用 const
  2. 需要重新賦值時,用 let
  3. 永遠不要用 var

JavaScript 變量的江湖恩怨:一篇文章徹底講清楚_變量聲明_20

這樣做的好處是:

  • 一眼就能看出哪些變量不會變
  • 降低認知成本
  • 代碼更安全、更自解釋

總結:變量,其實是人的影子

寫到這裏,我越來越覺得:

JavaScript 的變量聲明,其實特別像人。

var 像沒邊界感的老前輩,熱心但容易添亂

let 像講規則的現代職場人,清晰、可靠

const 像立下承諾的人,一旦決定就不會輕易改變

當你開始認真選擇變量聲明方式的時候,説明你已經不再只是“寫能跑的代碼”,而是在寫長期可維護的工程

END

如果你覺得這篇文章對你有幫助,歡迎點贊、在看、轉發,讓更多人認識變量鎮的三兄弟。

我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!