有時為了保護某些屬性,讓其無法被更改,我們會把他們設置為常量。
在某些語言里面,也許會用const來實現這樣的功能。本文講述如何在Javascript中實現這樣的功能。
方法一:
var myObject = { get readOnlyProperty() { return 1024; } }; alert(myObject.readOnlyProperty); // 1024 myObject.readOnlyProperty = 5; // 可以設置,但不管用 alert(myObject.readOnlyProperty); // 1024
如果你已經定義好了一個Object,那么你可以這么做
var myObject = {}; myObject.__defineGetter__("readOnlyProperty", function() { return 1024; });
上面的這兩段代碼兼容Firefox,Opera 9.5+, Safari 3+和Chrom,不過杯具的是,這些代碼是不兼容IE的。
方法二:
對於支持ECMAScript 5的Javascript解釋器,你可以使用Object.defineProperty方法來實現這樣的功能。
在松散模式,Javascript解釋器會直接忽略掉屬性的寫入。在嚴格模式(strict mode)下,解釋器會拋出一個錯誤。
var obj = {}; Object.defineProperty( obj, "<屬性名>", { value: "<屬性值>", writable: false, enumerable: true, configurable: true });
不過很明顯,這代碼是無法在那些不支持ECMAScript 5的瀏覽器(當然包括IE)上執行的。
方法三:
使用模塊模式去模擬出這樣的功能,不廢話,直接看代碼
var CONFIG = (function() { var private = { 'MY_CONST': '1', 'ANOTHER_CONST': '2' };
return { get: function(name) { return private[name]; } //函數返回一個對象,有get方法,接收name參數,返回內部私有變量的值 }; })(); alert(CONFIG.get('MY_CONST')); // 1 CONFIG.MY_CONST = '2'; alert(CONFIG.get('MY_CONST')); // 1 CONFIG.private.MY_CONST = '2'; // 錯誤,沒有private屬性 alert(CONFIG.get('MY_CONST')); // 1
這個方法兼容目前全部瀏覽器(包括IE),只是讀屬性的時候需要使用get。
方法四:
在大部分情況下,你並不需要完全控制變量不可寫。在業內有個約定,就是使用全大寫的字母來表示常量(只讀變量)。這是最簡單,最好的方法。
var MY_CONSTANT = "some-value";
這樣寫,來告訴自己,這個變量不可以改變!!!
方法五: “凍結”對象
1 var obj = {a:1}; 2 3 Object.freeze(obj); 4 5 obj.pro1 = 2; 6 7 console.log(obj.pro1);//顯示1
這里更厲害了,屬性特性什么的完全不管,直接將整個對象“凍結”。Object.freeze()函數在標准中的描述是“Prevents the modification of existing property attributes and values, and prevents the addition of new properties.”。即:阻止修改對象中現有屬性的值和特性,並阻止添加新屬性。這樣,整個對象都成了只讀的了,對象里面無論有多少屬性,統統都變成只讀的了。
方法六:. 閉包
前面用了一些看上去很炫酷的方法,提升一下B格,其實要說實現只讀,用的最多的當屬我大閉包了。
1 var cache = (function(){ 2 var a = 1; 3 4 return function(){ 5 return a; 6 } 7 8 })(); 9 10 console.log(cache());
這里用了閉包的緩存功能,將匿名函數中的a變量緩存起來,間接實現了只讀的功能。