JavaScriptで定数を作るには・・・
1 2 |
const HOGE = 123456; const FUGA = 'ABCDEF'; |
みたいに const を使うのが一般的だと思います。
でもあるとき、この方法だと期待通りの動作にならないことがありました。
というか定数定義なら、もっと確実な方法があったんです。
そこで自分への忘備録もかね、
ここでは JavaScriptでグローバル定数を定義する正しい方法 を解説!!
ちょうどPHPにおける define関数 みたいな実装方法です。
const による定数定義が上手くいかない場面
まず const がグローバルな定数定義に向いていない理由について。
それはブロックスコープだから
この一言に尽きます。
どういうことかというと、MDNでの説明を引用すると次の通り
定数 (const) は、 let 文を使って定義する変数と同じ、ブロックスコープです。定数の値は、再代入による変更はできず、再宣言もできません。
引用元 : const - JavaScript | MDN
別に関数内とかで一時的に使う定数なら、 const でも問題ありません。
でもスコープ関係なく、【本当にグローバルな定数】を作りたいときは不便なんです。
たとえば分かりやすい例を出すと、こういうコードですね。
▼ const が期待通りに動作しない例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/// デバッグ用フラグ var debug = true; if(!debug){ /// デバッグOFFのとき... const HOST_NAME = 'hoge.com'; const PROTOCOL = 'https'; } else{ /// デバッグONのとき... const HOST_NAME = 'hoge.me'; const PROTOCOL = 'http'; } /// 定数を表示してみる console.log('HOST_NAME : ', HOST_NAME); console.log('PROTOCOL : ', PROTOCOL); |
▼ 実際に上コードを実行すると、次のエラー発生
1 |
Uncaught ReferenceError: HOST_NAME is not defined at constants.js:24 |
if文内で const を使った定数はそのスコープ内だけで有効。
だからそのスコープ外では定数が参照できなくなるという訳です。
スコープ外に書けばいいけど、定数値を変えたいときも当然あります。
(たとえば実行環境に応じて定数を変えたり、デバッグ時とかだったり)
そんなときよさげな方法を見つけました。
グローバル定数を定義する正しいやり方
それは Object.defineProperty を使うこと
これはあるオブジェクトにプロパティ追加できる関数です。
▼ 詳しくは次のMDNリファレンス参照
静的メソッドの Object.defineProperty() は、あるオブジェクトに新しいプロパティを直接定義したり、オブジェクトの既存のプロパティを変更したりして、そのオブジェクトを返します。
このメソッドをうまく使うと、、、
取得できるけど変更不可なプロパティが作成可能。
つまりグローバルな定数が作れるという訳です。
PHPをご存知なら、 define関数 を想像すれば分かりやすいかも。
実際に Object.defineProperty で書いてみたコードは次の通りです。
▼ グローバル定数を定義する関数作ってみた
1 2 3 4 5 6 7 |
/// グローバル定数を定義する function define(name, value){ Object.defineProperty(window, name, { get: function(){return value;}, set: function(){throw(name+' is already defined !!');}, }); } |
上コードの window がプロパティ追加の対象。
あとは get で値を返すだけにして、 set で値代入されたときは例外を返してます。
▼ 実際の使い方はこういう感じ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/// デバッグ用フラグ var debug = true; if(!debug){ /// デバッグOFFのとき... define('HOST_NAME', 'hoge.com'); define('PROTOCOL', 'https'); } else{ /// デバッグONのとき... define('HOST_NAME', 'hoge.me'); define('PROTOCOL', 'http'); } /// 定数を表示してみる console.log('HOST_NAME : ', HOST_NAME); console.log('PROTOCOL : ', PROTOCOL); |
▼ 上コードの出力結果
1 2 |
HOST_NAME : hoge.me PROTOCOL : http |
グローバル定数は window に対して追加したので、どこからでも参照可能
アプリ全体で使う定数はこっちの方法を使うのが確実ですね。
おなじみの const は関数とかはグローバルな定数宣言には向いてません。
最後に…グローバル定数宣言のまとめ
ということで、ここまでの要点まとめ
- グローバル定数に const はNG
なぜなら関数とかのスコープ {} 内部でしか参照できないから
- 代わりに hasPropery 使用がベスト!
具体的には window に対して読み込み専用のプロパティを追加すればOK
デバッグ時とかで定数値を変えたいときに使えるテクニックです。
以上、JavaScriptで正真正銘のグローバル定数を作る方法でした。
ではまた。バイバイ($・・)/~~~