オブジェクト指向JavaScriptの原則という本で知ったのですが、ECMAScript 5からはオブジェクトをロックする機能があるようで、プロパティの追加や削除の禁止だけでなく、値の書き換えのようなこともできる方法があるようです。これで定数のようなことができそうだと思ってやってみました。Object.freezeというメソッドを使うとできるようです(参考:Object.freeze – JavaScript | MDN)。
var TAX = { TAXRATE : 0.08, INCLUDE_TAX : function(price){ return (this.TAXRATE+1)*price; } }; Object.freeze(TAX); TAX.TAXRATE = 0.1; TAX.INCLUDE_TAX = function(price){ return (1-this.TAXRATE)*price; }; TAX.YEAR = 2014; // もし値が変更されていれば、『0.1』になる console.log(TAX.TAXRATE); //=> 0.08 // もし値が変更されていれば、『90』になる console.log(TAX.INCLUDE_TAX(100)); //=> 108 // もし値が追加されていれば、2014になる console.log(TAX.YEAR); //=> undefined
確かに、Object.freezeメソッドを使うとオブジェクトの値が変更することができなくなりました。試しに、『Object.freeze(TAX);』の箇所を削除してみるとconsole.logの出力はそれぞれ『0.1』、『90』『2014』となりました。
ところで、定数というと思いつくのはむしろconst宣言だと思います(参考:const – JavaScript | MDN)。
ただし、const宣言にはIEは10以前では対応していなかったりそもそもECMAScriptで定義されていないなどいろいろ問題もあります(Object.freezeはIE9より対応)。さらにいうと、constで宣言したオブジェクト変数の値は変更できてしまいます。
const TEST = { ENGLISH : 60, MATH : 80, SCIENCE : 70 } TEST.ENGLISH = 90; console.log( TEST.ENGLISH ); //=> 90 TEST.SOCIAL = 66; console.log( TEST.SOCIAL ); //=> 66 TEST = null; // オブジェクト自体の変更はできない console.log(TEST); //=> Object {ENGLISH: 90, MATH: 80, SCIENCE: 70, SOCIAL: 66}
ここまで書いて、ふと、そういえばさっきObject.freezeでプロパティ値の書き込みをできないようにしたサンプルではオブジェクト自体を変更してなかったなと思ってやってみた。
TAX = null; console.log(TAX); //=> null
変更できてしまった・・・。
const宣言+Object.freeze()というのがある意味一番いいのかもしれません(そもそも、定数をオブジェクトとして扱う必要ってそんなにないような気もしますが・・・)。
const TEST = { ENGLISH : 60, MATH : 80, SCIENCE : 70 } Object.freeze(TEST); TEST.ENGLISH = 90; console.log( TEST.ENGLISH ); //=> 60 TEST.SOCIAL = 66; console.log( TEST.SOCIAL ); //=> undefined TEST = null; console.log(TEST); //=> Object {ENGLISH: 60, MATH: 80, SCIENCE: 70}
2014年8月26日追記
このfreezeってオブジェクト内のメソッドからでも変更できないだろうかと思い、試してみた。
var TAX = { TAXRATE : 0.08, CHANGE_TAX : function(tax){ this.TAXRATE = tax; } }; Object.freeze(TAX); TAX.CHANGE_TAX(0.1); console.log( TAX.TAXRATE ); //=> 0.08
変更できませんでした(『Object.freeze(TAX);』の行をコメントアウトすると、0.1となる)。
コメント