JavaScripのグローバル定数の正しい作り方…PHPのdefine的実装

JavaScriptで定数を作るには・・・

みたいに const  を使うのが一般的だと思います。

でもあるとき、この方法だと期待通りの動作にならないことがありました。

というか定数定義なら、もっと確実な方法があったんです。

そこで自分への忘備録もかね、
ここでは JavaScriptでグローバル定数を定義する正しい方法 を解説!!

ちょうどPHPにおける define関数 みたいな実装方法です。

const による定数定義が上手くいかない場面

まず const  がグローバルな定数定義に向いていない理由について。

それはブロックスコープだから

この一言に尽きます。

 

どういうことかというと、MDNでの説明を引用すると次の通り

定数 (const) は、 let 文を使って定義する変数と同じ、ブロックスコープです。定数の値は、再代入による変更はできず、再宣言もできません。

引用元 : const - JavaScript | MDN

別に関数内とかで一時的に使う定数なら、 const  でも問題ありません。

でもスコープ関係なく、【本当にグローバルな定数】を作りたいときは不便なんです。

 

たとえば分かりやすい例を出すと、こういうコードですね。

▼ const が期待通りに動作しない例

▼ 実際に上コードを実行すると、次のエラー発生

if文内で const  を使った定数はそのスコープ内だけで有効。

だからそのスコープ外では定数が参照できなくなるという訳です。

スコープ外に書けばいいけど、定数値を変えたいときも当然あります。
(たとえば実行環境に応じて定数を変えたり、デバッグ時とかだったり)

そんなときよさげな方法を見つけました。

グローバル定数を定義する正しいやり方

それは Object.defineProperty を使うこと

これはあるオブジェクトにプロパティ追加できる関数です。

▼ 詳しくは次のMDNリファレンス参照

静的メソッドの Object.defineProperty() は、あるオブジェクトに新しいプロパティを直接定義したり、オブジェクトの既存のプロパティを変更したりして、そのオブジェクトを返します。

引用元 : Object.defineProperty() - JavaScript | MDN

このメソッドをうまく使うと、、、

取得できるけど変更不可なプロパティが作成可能。

つまりグローバルな定数が作れるという訳です。

PHPをご存知なら、 define関数 を想像すれば分かりやすいかも。

 

実際に Object.defineProperty  で書いてみたコードは次の通りです。

▼ グローバル定数を定義する関数作ってみた

上コードの window  がプロパティ追加の対象。

あとは get  で値を返すだけにして、 set  で値代入されたときは例外を返してます。

 

▼ 実際の使い方はこういう感じ

▼ 上コードの出力結果

グローバル定数は window  に対して追加したので、どこからでも参照可能

アプリ全体で使う定数はこっちの方法を使うのが確実ですね。

おなじみの const  は関数とかはグローバルな定数宣言には向いてません。

最後に…グローバル定数宣言のまとめ

ということで、ここまでの要点まとめ

  • グローバル定数に const はNG
    なぜなら関数とかのスコープ {} 内部でしか参照できないから
  • 代わりに hasPropery 使用がベスト!
    具体的には window  に対して読み込み専用のプロパティを追加すればOK

デバッグ時とかで定数値を変えたいときに使えるテクニックです。

以上、JavaScriptで正真正銘のグローバル定数を作る方法でした。

ではまた。バイバイ($・・)/~~~