經過 es5實現const
這個問題來查找百度javascript
var obj = {}; obj.a = 1; obj.b = 2; //等價於 var obj = { a: 1, b: 2 } //等價於 var obj = {}; Object.defineProperty(obj, "a", { value: 1, //初始值 writable: true, //可寫 configurable: true, //可配置 enumerable: true //可枚舉 }); Object.defineProperty(obj, "b", { value: 2, //初始值 writable: true, //可寫 configurable: true, //可配置 enumerable: true //可枚舉 });
Object.defineProperty(),該方法是ES5規範中的,該方法的做用是在對象上定義一個新屬性,或者修改對象的一個現有屬性,並對該屬性加以描述,返回這個對象,咱們來看一下瀏覽器兼容性:java
特性 | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
基本支持 | 4.0 (2) | 5 | 9 [1] | 11.60 | 5.1 [2] |
天煞的IE8瀏覽器
Object.defineProperty() 方法能夠定義對象屬性的數據描述和存儲描述函數
configurable
es5當且僅當該屬性的 configurable 爲 true 時,該屬性
描述符
纔可以被改變,也可以被刪除。默認爲false
。code
enumerable
對象
當且僅當該屬性的 enumerable 爲 true 時,該屬性纔可以出如今對象的枚舉屬性中。
默認爲false。
ip
value
it該屬性對應的值。能夠是任何有效的 JavaScript 值(數值,對象,函數等)。默認爲
undefined
。io
writable
當且僅當該屬性的 writable 爲 true 時,該屬性才能被
賦值運算符改變。
默認爲false
。
用常規方法定義屬性的時候,其除 value 之外的數據描述符默認均爲 true ,當咱們用 Object.defineProperty() 定義屬性的時候,默認爲 false。
因此定義常量能夠是
var CONST = {}; Object.defineProperty(CONST, "A", { value: 1, enumerable: true }); Object.defineProperty(CONST, "B", { value: 2, enumerable: true });
對象常量
Object.preventExtensions() 方法能夠讓一個對象不可擴展,該對象沒法再添加新的屬性,可是能夠刪除現有屬性:
var CONST = {}; CONST.A = 1; CONST.B = 2; Object.preventExtensions(CONST); delete CONST.B; console.log(CONST); //CONST: { A: 1} CONST.C = 3; //錯誤!對象不可擴展
Object.seal() 來對一個對象密封,該方法會阻止對象擴展,並將該對象的全部屬性設置爲不可配置,可是可寫:
var CONST = {}; CONST.A = 1; CONST.B = 2; Object.seal(CONST); CONST.A = 3; console.log(CONST.A); //3 Object.defineProperty(CONST, "B", { value: 2, writable: true, configurable: true, //錯誤!屬性不可配置 enumerable: false, //錯誤!屬性不可配置 }) CONST.C = 3; //錯誤!對象不可擴展 Object.seal = function (obj) { Object.preventExtensions(obj); for (var key in obj) { Object.defineProperty(obj, key, { value: obj[key], writable: true, configurable: false, enumerable: true }) }; return obj; }
兩個方法基礎上,咱們能夠 Object.freeze() 來對一個對象進行凍結,實現常量的需求,該方法會阻止對象擴展,並凍結對象,將其全部屬性設置爲只讀和不可配置:
var CONST = {}; CONST.A = 1; CONST.B = 2; Object.freeze(CONST); CONST.A = 3; //錯誤!屬性只讀 Object.defineProperty(CONST, "B", { value: 3, //錯誤!屬性只讀 writable: true, //錯誤!屬性不可配置 configurable: true, //錯誤!屬性不可配置 enumerable: false, //錯誤!屬性不可配置 }) CONST.C = 3; //錯誤!對象不可擴展 Object.freeze = function (obj) { Object.preventExtensions(obj); for (var key in obj) { Object.defineProperty(obj, key, { value: obj[key], writable: false, configurable: false, enumerable: true }) }; return obj; }
最終
//第一種方法:屬性層面,對象可擴展 var CONST = {}; Object.defineProperty(CONST, "A", { value: 1, enumerable: true }); //第二種方法:對象層面,對象不可擴展 var CONST = {}; CONST.A = 1; Object.freeze(CONST);