JavaScript常量真的不可變嗎?

JavaScript常量真的不可變嗎?

image.png




做者 | Brian Rinaldi譯者 | 張蘭月編輯 | YonieJavaScript 中的常量究竟如何工做,常量就是「在正常執行中沒法被程序改變的值」嗎?事實就是如此嗎?非也,本文將給你答案。

前幾天我在 Twitter 上談到了 JavaScript 中的 const。Kyle Simpson 指出我以前分享的一篇文章中有關於 const 的一個誤解。但個人想法是,至少我能理解這種糊塗來自哪裏,由於 const 與我預想的工做方式不太同樣(注,我並非說 const 是錯的,只是說它與個人預想有差異。)javascript


image.png

雖然我跟 Kyle Simpson 對話很短,可是這段對話仍然涉及到了許多詞彙和概念。所以我以爲本身不妨深刻研究一下,從而使本身不只更加理解常量的概念,並且更加了解用 const 聲明的變量在 JavaScript 中究竟是如何工做的。html

須要指出的是,Kyle Simpson 的確寫過一篇關於此主題的帖子,可是這篇博客已經下線了。並且他的確經過 Wayback Machine 分享過一個版本。這篇博客值得一讀,由於他寫得很深刻: https://web.archive.org/web/20151113135159/http:/blog.getify.com/constantly-confusing-const前端

什麼是常量

若是你在谷歌搜「什麼是編程中所謂的常量?」,你會發現許多頁面將常量定義爲維基百科中定義的那樣,即「在正常執行中沒法被程序改變的值。」java

表面上看,這彷佛很簡單,就是設置一個值,一個沒法改變的值。這對於可讀性和錯誤檢查會十分有用。可是,並不是全部語言都有常量,並且擁有常量的各個語言處理常量的方式也不太同樣。例如,在一些語言中,常量所表明的值的類型是有限的。程序員

一旦你走出簡單的值類型範圍後,事情就會變得使人糊塗了。這一點很重要,這也是我對 JavaScript 中的常量感到糊塗的起點。這裏,我會舉一個例子,而不是解釋。如今,假設我要像這樣設置一個常量:web

const NAME = "Brian";

彷佛很明顯的是,給 NAME 指定任何新的值都會出現錯誤。可是,若是我像下面這樣作呢:編程

const ME = {name:'Brian'};

若是我改變 ME.name 的值,是否還會出錯?有人會說本質上我並無改變 ME 的值,由於它仍然指向一樣的對象,即便這個對象已經被改變了。但要說明的是,在 JavaScript 中,這並不會出錯。微信

image.png

在這裏,會出現計算機科學家們熟悉的概念,那就是基元和不變性。咱們會談一點這方面的內容,但爲了不讓本文成爲一本計算機科學書籍,我不會深刻地探討這兩個概念。ide

簡單來講,不可改變的對象是指一個建立後便沒法改變其狀態的對象。而 JavaScript 中的基元是指「一個不是對象但沒有方法的數據。」 (來源:MDN)函數

JavaScript 中的常量

JavaScript ES6(又稱 ES2015) 中加入了 const 關鍵詞。以前,一般的約定是使用一個標準的變量,但它必須以全大寫命名,如 MY_CONSTANT。但這並無真正規定一個變量是否可以被更改,它只是對程序員的一個提示,提示他們不要更改該變量。

用 const 聲明的 JavaScript 常量能夠是全局範圍的,也能夠是區塊範圍的。若是常量位於區塊內(即在{ 和}之間),它們就自動是區塊範圍的。若是它們沒有在區塊內,則它們是全局範圍的。可是,與用 var 聲明的變量不一樣的是,它們不會成爲 window 對象的特性。若是它們位於模塊中,位於區塊外用 const 聲明的變量對於該模塊而言將是全局範圍的。

const 和 var 另外一個有趣的區別在於,它們提高 (hoist) 的方式不一樣。當你用 const 或 let 聲明一個變量時,該聲明將被提高,可是它的初始化值並非 undefined,所以若是你嘗試在聲明前訪問它的話,會出現引用錯誤。正以下面所示,第一個 console.log 引用了以 var 定義的變量,它的返回值爲 undefined。而第二個 console.log 引用了以 const 定義的變量,卻出現了一個錯誤。image.png


這一現象被稱之爲暫時性死區,這個名字使它聽起來比實際上更加不吉利。

如前所述,最後一條關於 JavaScript const 重要的一點是:const 聲明爲一個值建立了一個只讀的引用。這並非說其表明的值是不可改變的,而只是說變量標識符不能被從新指定罷了。來源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

這也是關於 const 的困惑再次出現的地方。當你將 const 用於 JavaScript  基元類型(如布爾值、數字、字符串等)時,const 的行爲與你預想的一致(任何從新指定值的嘗試都會致使錯誤)。可是,當你將 const 用於 JavaScript 對象時(包括數列、函數等),這個對象仍然是能夠更改的,也就是說,這個對象的特性仍然能夠被更改。

想要了解 let 和 const 做用域的詳情,請閱讀 Axel Rauschmayer 的 「爲沒耐心的程序員設計的 JavaScript」這篇文章: https://exploringjs.com/impatient-js/ch_variables-assignment.html

若是你想參與更多前端技術交流,獲取更多專家分享,能夠加入咱們的「前端技術交流羣「,社羣內會常常討論前端相關的技術、分享免費學習資料,咱們也會邀請前端專家進行社羣分享、直播、公開課等活動。 若是你感興趣,歡迎添加社羣管理員微信GeekUni004,回覆「前端羣」申請入羣。
你應該用 Const 嗎? 

回答這個問題有點難,特別是由於 let 擁有一樣的區塊做用域和提高優點(我將後者描述爲一個潛在的優點,由於若是你在聲明某個變量前不當心訪問了某個變量的話,你提高 var 的方式可能會致使出現不太常見的錯誤)。鼓吹 const 優點的人一般關注於代碼的可讀性。經過使用 const,你至關於代表了這個特定的變量不該該被更改,而且在某種程度上,你強調了這一點。然而,人們好像常常對此產生誤解這一事實把支持 const 可讀性的觀點給削弱了,就像本文開頭所講的那樣。這的確可以必定程度上防止他人從新指定這個變量的值,可是我想引用一下 Kyle 的話:

事實上,許多程序員都認可,這一保護可以避免一些不知情的程序員意外地改變某個 const。然而,有個例外,我認爲在現實中極可能發生的狀況是,當一個程序員須要更改某個變量但卻得到了一個「const- 拋出」錯誤時,他可能會將 const 直接修改爲 let,而後繼續工做。

因此,若是 const 提供的保護較爲有限的話,那麼咱們可能只須要在意風格偏好了,特別是在 let 和 const 之間作選擇時。但若是你的變量須要表明一個基元值,並且這個基元值並不會改變,那麼很顯然,使用 const 是個合理的選擇。可是,請注意,若是該值並不是一個基元值,那麼從可讀性的角度來說,使用 const 會給人帶來更多困惑,而不是幫助。

英文原文:https://remotesynthesis.com/blog/javascript-const

相關文章
相關標籤/搜索