應該使用 const 定義 object 和 array 嗎?
可分為node端和web,當然web端編譯後會變成var,但只討論問題,不考慮編譯和兼容。
技術上const定義object和array肯定是可以的,因為指針類的地址並沒有更改。 對象或數組依舊可以push等。const a = 10;
a= 20 // errorconst b = [];
b.push( 100 ) // okconst c = {};
b["test"] = 100 // ok
b.test = 100 // ok
我老早就說了,能用 const 就應該用 const。比如開啟 eslint 的 prefer-const 的 rule。
有一些人,因為覺得 const 表示常量,而實際上並不是常量,所以認為不應該用。這是一種因果倒置。
固然在一些語言里,const 表示的是編譯期常量,但是也有不少語言里 const 表示的就是不可變,和 js 里的 const 意義是一致的。比如 C++。
我雖然確實認為 js 用 const 關鍵字表達這個語義(以及用 let 表示可變)不是最佳選擇(我認為最佳選擇是用 let 表示不可變,用 let var 表示可變),但是畢竟這只是一個語法上的小節,對程序員來說,並沒有什麼難以掌握的。
如果說,使用了 const 產生誤解,說明(誤解它的程序員)沒有正確理解 const 的語義。正確的對策是教育,而不是遷就。
至於說還想表達 immutable array / object,目前在原生 js 里沒有很好的辦法(雖然可以用 Object.freeze/seal 之類的),確實如此。但是缺乏某一種特性難以構成不使用另一種特性的理由。況且如果真的認為這意義重大,可以用 typescript(readonly 類型)。
以上。
正確的邏輯應該是:
你認為它不應該被重新定義,使用const;你需要它完全不可改變,用Object.freeze或者typescript的readonly;而不是:
我希望它不可變,然而用const之後它還是可變,所以不用const理解它的語義,並用正確的關鍵詞做正確的事。看需要。
雖然用const聲明object只能保證object指向的內存地址不變,而不能保證object里的數據結構不變,但確保了這個變數不會被其他類型的值覆蓋。
正如你說的可以這樣:
const life = {};
life.length = 90;
不能這樣:
const life = {};
life = "+1s"; // error
但如果你本來就想讓這個object變數被賦成其他類型,就需要用let了。
let life = {};
life = "+1s"; // ok
而如果你想讓這個object變數的數據結構也保持不變,那這個問題已經超出const和let的範圍了。
因此沒有絕對的應不應該,一切都看場景。
如果是邏輯上就應該是常量的,當然應該使用const,當然如果是功能上需要不能改動還是要用 Object.freeze
不管是使用var、let定義的變數,還是const定義的常量,如果將一個引用類型的值賦值給這個變數(常量),這個變(常)量都只是一個指針,這個指針指向了內存中的對象,而無法保證其指向的數據結構的變化。如題主所說,可以push,pop等操作
但是const(常量的意思)作為定義一個常量的關鍵字,還是不要對這個常量做出數據結構的改變,因為這即不符合語義,又讓後來者不好理解代碼
我覺得 const 定義有問題 不應該只是地址不變 地址引用的對象也應該不變。
我覺得用的時候可以自我編譯const常量,一般程序中80%是const 另20%是let 是一件美好的事情
應當,而且若不是歷史包袱,應當是默認const
const能夠很大的幫助減少程序中的缺陷,同時不變性對多線程數據一致性也是有極大好處的
理想的方式就是不用寫const,默認全const,除非顯示加入mut才可寫,這是rust的方式- immutability並不重要,我知道FB的人說他很重要,很多大神都說他很重要,但它並不重要
- 如果重構ES5項目到ES6,我replace成let,let的適應性更好
- let是更好的var,const不是更好的var
- var時代JS欣欣向榮,var沒有拖過後退
- 你總有不得不用let的時候
const的意義:保證變數指向的內存地址不發生變化。
對於值是基本類型的變數,具有完全不可變性,地址和數據均不可變;對於值是引用類型的變數,數據具有部分不可變性,內存地址不可變,數據可變。
也就是說,使用const的定義的變數,牢牢地與value綁定在一起,而且這種綁定是不可解除的,但是這種綁定,指的是整體的綁定,也就是內存地址上的綁定。舉例來說:const str = "foo" ,『str永遠指向"foo"的內存地址;對於const obj ={name:"foo"},obj永遠指向{}的內存地址,指向內容不包含對象數據。
做一個很形象的類比小故事:你的0歲到23歲
//剛出生的你,父母給予了生命的同時,給予了你一個名字 Jack,落地1歲
const you = {}
you.name="Jack",
you.age=1
//7歲,你上了小學
you.age = 7
//13歲,小學畢業,開始讀初中
you.age = 13 , you.primary = true
//16歲,初中畢業。開始讀高中
you.age = 16 , you.junior = true
//19歲,高中畢業,開始讀大學
you.age = 19 , you.high = true
//23歲,大學畢業,開始工作
you.age = 23 , you.university = true , you.salary = "RMB 100 yuan"
故事還在繼續......
但是,你始終是你,你的父母始終是你的父母,即使到了66世紀,這是亘古不變的。但是在這一路上,你的age屬性在發生變化,你解鎖了小學,初中,高中,大學畢業證等一系列證書,工作後也新增了薪酬這個新屬性,雖然只有可憐的100塊。
或許有一天,you.girlfriend = "Rose"
又或許有一天,you.baby = little Jack"
回過頭來分析下剛出生的你const you = {name:"Jack",age:1}
const不能重新定義:試問一下,在這個世界,你還能重新出生一次嗎?const必須賦初始值: const you = {}是一個整體,誰都不能少,因為你本身是一個完整的整體,在{}.prototype你遺傳了父母的基因。const不能重新賦值:you = {name:"Tom",age:18},據我所致,目前還沒有什麼技術可以實現克隆人的複製粘貼。const複雜類型可變:name和age這些屬性,則是後期為你新增的新屬性,這些數據是有限且可變的,例如age,salary等等。
但是在另外一個世界,也就是另外一個作用域(塊作用域或函數局部作用域),you can reborn
const a = 1
if(a === 1){
const a = 2
}
//all is well
const b = 1
function j(){
const b = 1
}
//all is well
因此,當有那麼一個object或者array時,就像故事中的you一樣,無論風吹雨打,本質(內存地址不變)亘古不變時,極大程度上確保變數不被完全重新賦值時,就可以用const來定義。
MDN 關於const 上這麼說的
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object"s contents (e.g. its parameters) can be altered.
所以const只是表示variable不可以被重新賦值,但是對於object或者array還是mutable的,也就是說可以改變其的內容或元素
不管是編程還是別的領域,在有兩種或者多種解決方案的時候,一定不能將思維局限於一種情形之下,那樣一定是不嚴謹的。
你只要理解var let const 這些東西的存在,然後選擇一個不會讓你代碼報錯的方法即可。
哪來那麼多絕對、一定、應該呢?我的理解是 const 不可變的 量
對於引用賦值的數據類型 那麼 只要 指針不變,也就是說不用一個新的對象覆蓋 都是可以的
對於字元串這種非引用賦值的類型則不能更改值
如果把const 理解成常量 那 php 還有 define() 和 const 之分呢....
用let,因為少打兩個字母,且附帶避免作用域提升。
推薦閱讀:
※現在前端必須掌握nodejs技術嗎?
※為什麼 Node.js 做的站點可以不用 nginx / Apache 這類 Web server 軟體?
※前端構建工具 Gulp / browserify/ webpack / npm ?
※npm和bower都有的模塊怎麼選擇?
※手機遊戲伺服器端用node.js 還是用go,fibjs之類等比較好?
TAG:JavaScript | Nodejs |