在es6中,可以使用const關鍵字來聲明只讀常量,語法“const 常量名 = 常量值;”;一旦聲明,常量必須進行初始化且初始化的值就不能改變。const聲明的常量屬于塊作用域,受到“暫存死區”的約束,不會在window上創建任何全局屬性,不可重新分配,不可重新聲明。
本教程操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。
在es6中,可以使用const關鍵字來聲明只讀常量。
es6 const關鍵字
const聲明一個只讀的常量。一旦聲明,常量必須進行初始化且初始化的值就不能改變。
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable.
const 常量遵守以下規則:
-
是屬于塊作用域的。
-
受到“暫存死區”的約束。
-
它不會在 window 上創建任何全局屬性。
-
不可重新分配。
-
不可重新聲明。
const一旦聲明變量,就必須立即初始化。
const foo; // SyntaxError: Missing initializer in const declaration
上面代碼表示,對于const來說,只聲明不賦值,就會報錯。
const的作用域與let命令相同:只在聲明所在的塊級作用域內有效。
if (true) { const MAX = 5; } MAX // Uncaught ReferenceError: MAX is not defined
const命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置后面使用。
if (true) { console.log(MAX); // ReferenceError const MAX = 5; }
上面代碼在常量MAX聲明之前就調用,結果報錯。
const聲明的常量,也與let一樣不可重復聲明。
var message = "Hello!"; let age = 25; // 以下兩行都會報錯 const message = "Goodbye!"; const age = 30;
const本質
const實際上保證的,并不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對于簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同于常量。但對于復合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至于它指向的數據結構是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心。
const foo = {}; // 為 foo 添加一個屬性,可以成功 foo.prop = 123; foo.prop // 123 // 將 foo 指向另一個對象,就會報錯 foo = {}; // TypeError: "foo" is read-only
上面代碼中,常量foo儲存的是一個地址,這個地址指向一個對象。不可變的只是這個地址,即不能把foo指向另一個地址,但對象本身是可變的,所以依然可以為其添加新屬性。
下面是另一個例子。
const a = []; a.push('Hello'); // 可執行 a.length = 0; // 可執行 a = ['Dave']; // 報錯
上面代碼中,常量a是一個數組,這個數組本身是可寫的,但是如果將另一個數組賦值給a,就會報錯。
如果真的想將對象凍結,應該使用Object.freeze方法。
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] ); } }); };
【