萬萬沒想到!ES6的const並非一定為常量
對於ES6的const變數,大家一直存在誤會,這篇部落格將試著解開真相。
const的本質
const定義的變數並非常量,並非不可變。使用const定義的物件或者陣列,其實是可變的。下面的程式碼並不會報錯:
const foo = {}; foo.name = "Fundebug"; console.log(foo.name); // 列印"Fundebug"
為什麼會這樣?下面引用大神阮一峰的ECMAScript 6 入門
const實際上保證的,並不是變數的值不得改動,而是變數指向的那個記憶體地址所儲存的資料不得改動。對於簡單型別的資料(數值、字串、布林值),值就儲存在變數指向的那個記憶體地址,因此等同於常量。但對於複合型別的資料(主要是物件和陣列),變數指向的記憶體地址,儲存的只是一個指向實際資料的指標,const只能保證這個指標是固定的(即總是指向另一個固定的地址),至於它指向的資料結構是不是可變的,就完全不能控制了。因此,將一個物件宣告為常量必須非常小心。
因此,當我們使用賦值運算子, 一元運算子以及字尾運算子對const變數進行修改時,會出現“TypeError:Assignment to constant variable”報錯:
const foo = 27; // 下面任意一個表示式都會報錯:TypeError: Assignment to constant variable. foo = 42; foo *= 42; foo /= 42; foo %= 42; foo += 42; foo -= 42; foo <<= 0b101010; foo >>= 0b101010; foo >>>= 0b101010; foo &= 0b101010; foo ^= 0b101010; foo |= 0b101010; --foo; ++foo; foo--; foo++;
如何定義常量?
對於數值、字串和布林值變數,使用const定義的話是不可變的:
const name = "Fundebug"; name = "雲麒"; // 報錯:TypeError: Assignment to constant variable.
使用Object.freeze()可以讓物件不可變,這個API從ES5開始就有了。
const foo = Object.freeze( { 'name': "Fundebug" }); foo.name = "雲麒"; // 嚴格模式("use strict")下報錯:Uncaught TypeError: Cannot assign to read only property 'bar' of object '#<Object>' console.log(foo.name); // 非嚴格模式下列印"Fundebug"
注意,Object.freeze()是有侷限性的,物件中巢狀物件仍然可以被修改。MDN提供了一下deepFreeze示例程式碼,是利用Object.freeze()實現的,可以讓巢狀物件也不可變。
另外,Object.freeze()僅對鍵值對有效。對於Date, Map和Set,目前還沒有相應方法。因此有人提議在ECMAScript標準中新增不可變的Map和Set等資料型別。
const和let如何選擇?
const和let的唯一區別在於,const可以讓數值、字串和布林變數不可變。
以上所說的內容都是事實,下面我想表達一下自己的觀點。
const可以提高程式碼的可讀性,因為const定義的數值、字串和布林變數是不可變的,而const定義的物件始終指向同一個物件。而使用let時,不能保證這些。因此,對於let和const,我們應該這樣選擇:
- 預設使用const
- 僅當變數需要修改時使用let
- 不要使用var
你是否同意我的觀點呢?歡迎大家交流討論~
相關文章
- 萬萬沒想到!ModelArts與AppCube組CP了APP
- 萬萬沒想到——flutter這樣外接紋理Flutter
- 萬萬沒想到,我的煉丹爐玩壞了
- 面試題2:萬萬沒想到之抓捕孔連順面試題
- AI在用| 萬萬沒想到,科技論文還能這麼讀AI
- 【問題總結】萬萬沒想到,竟然栽在了List手裡
- 萬萬沒想到,騰訊視訊也開始做遊戲了遊戲
- 萬萬沒想到,go的資料庫操作,也能像php一樣溜了Go資料庫PHP
- 萬萬沒想到,程式設計師的一天竟然是這樣....程式設計師
- 這些神奇又搞笑的bug,真的讓程式設計師萬萬沒想到!程式設計師
- Python爬蟲新手教程:Python分析了 7 萬款 App,萬萬沒想到Python爬蟲APP
- C++ const常量的理解C++
- 萬萬沒想到!《聖歌》是北美地區目前為止2019年銷量排名第五的遊戲遊戲
- 萬萬沒想到,一個 MongoDB.Driver 的 bug 導致 .NET5 程式死鎖!MongoDB
- GitHub 2018年度報告 | 萬萬沒想到你是這樣的程式設計師Github程式設計師
- 理解let並 const在JavaScript ES6中(4)JavaScript
- 理解let並 const在JavaScript ES6中(1)JavaScript
- 理解let並 const在JavaScript ES6中(2)JavaScript
- 萬萬沒想到,我在夜市地攤解決了MySQL臨時表空間難題~~MySql
- 萬萬沒想到,學習風變程式設計Python課程還有這個用處程式設計Python
- 萬萬沒想到一個普通的地區問題,竟然讓我們大戰了300回合
- 萬萬沒想到,iPhone手機拍照也能自帶水印,再也不用羨慕安卓了iPhone安卓
- 小小樹葉,藏著哪些技術之道?你一定沒想到
- Golang 學習——常量 const 和 iotaGolang
- PHP 定義常量 define 和 const的區別PHP
- go 學習筆記之萬萬沒想到寵物店竟然催生出面向介面程式設計?Go筆記程式設計
- ES6 let和const
- ES6之let、const
- ES6 之 let / const
- ES6-const宣告常量以及特點
- ES6 let和const命令
- ES6之const和let
- 重學ES6 let & const
- ES6之var、let、const
- 2020年我的幾個沒想到
- 常量引用或指向常量的指標,其所指物件可以是非const物件(C++)指標物件C++
- ES6中var,let,const的區別
- es6 let const與var 的區別