在咱們使用const聲明常量時,總認爲值一旦聲明就不可改變,實際上是有誤解的;數組
剛在看ES6標準文檔時,仔細閱讀了const的解析,恍然大悟的感受,分享給你們。數據結構
const
實際上保證的,並非變量的值不得改動,而是變量指向的那個內存地址不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,所以等同於常量。函數
但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指針,const
只能保證這個指針是固定的,至於它指向的數據結構是否是可變的,就徹底不能控制了。所以,將一個對象聲明爲常量必須很是當心。spa
const foo = {}; // 爲 foo 添加一個屬性,能夠成功 foo.prop = 123; foo.prop // 123 // 將 foo 指向另外一個對象,就會報錯 foo = {}; // TypeError: "foo" is read-only
上面代碼中,常量foo
儲存的是一個地址,這個地址指向一個對象。不可變的只是這個地址,即不能把foo
指向另外一個地址,但對象自己是可變的,因此依然能夠爲其添加新屬性。指針
下面是另外一個例子。code
const a = []; a.push('Hello'); // 可執行 a.length = 0; // 可執行 a = ['Dave']; // 報錯
上面代碼中,常量a
是一個數組,這個數組自己是可寫的,可是若是將另外一個數組賦值給a
,就會報錯。對象
若是真的想將對象凍結,應該使用Object.freeze
方法。blog
const foo = Object.freeze({}); // 常規模式時,下面一行不起做用; // 嚴格模式時,該行會報錯 foo.prop = 123;
上面代碼中,常量foo
指向一個凍結的對象,因此添加新屬性不起做用,嚴格模式時還會報錯。內存
除了將對象自己凍結,對象的屬性也應該凍結。下面是一個將對象完全凍結的函數。文檔
var constantize = (obj) => { Object.freeze(obj); Object.keys(obj).forEach( (key, i) => { if ( typeof obj[key] === 'object' ) { constantize( obj[key] ); } }); };