[JavaScript] 定数の扱い方:constとは? Object.freeze()との違いも解説
定数というのは、あえて単純化して言えば「変数の参照先を変更できなくする」こと。
変数の「中身」が対象なのではなく、「変数」そのものが対象だ。
厳密には、「変数を定数とする」というのはおかしな言い方だが、こう考えたほうがわかりやすい。
基本的に、変数(variable number)に対して定数(constant number)と呼ぶ。
定数にオブジェクトを割り当てた場合、あくまで「変数」が定数としてロックされるのであって、そのオブジェクト自体がロックされるのではけっしてない。
よって、オブジェクトのプロパティなどを変更することができるのは、むしろ当然なのだ。
[javascript]
const example = {abc : 1, bcd : 2};
// 変更可能
example.abc = 3;
// エラー:const指定の変数(定数)exampleの参照先は変えられない
example = {cde : 4};
[/javascript]
C++の経験者なら、この辺のことはすでに把握していることだろう。
C++では、変数や引数をconst指定することと、オブジェクト(クラス)をconst指定することはまったく意味が異なるからだ。
[cpp]
const Example* const ex = new Example();
[/cpp]
この例の場合、exというポインタ変数を定数とすることでその参照先(Exampleクラスのインスタンス)を変えられなくしている。
ここまではJavaScriptと似たようなものだが、その上でExampleインスタンスもconst指定することで、その中身(メンバ変数)の状態を変更できなくしている。
(厳密には、変更できてしまうメンバ変数・メンバ関数の呼び出しを禁止している)
残念ながら、JavaScriptにはこうした文法は存在しない。
だが、実は「Object.freeze()」というメソッドが存在し、これを使うと事実上同じことができる。
[javascript]
const example = {abc : 1, bcd : 2};
Object.freeze(example);
[/javascript]
このようにすると、既存のプロパティの中身=参照先を変更できないだけでなく、新規のプロパティも追加できない。
ただ、この場合、オブジェクトの中身を変更しようとしても、通常はエラー(例外)は出ず、strict modeのときだけ例外が投げられる。
[javascript]
// strict modeではエラー
example.abc = 3; // 既存プロパティ
example.cde = 1; // 新規プロパティ
[/javascript]