【JavaScript】再定義不可のグローバル変数(定数)を定義

謎のプリン語る。
プログラミングの役立つ情報とか、どうでもいい雑談とか書いてます。
一人書く人増えました。

【JavaScript】再定義不可のグローバル変数(定数)を定義

みやびプリン 500 316

500 320

【JavaScript】再定義不可のグローバル変数(定数)を定義 - サムネイル

※この記事は5年以上前の記事です。
現在は状況が異なる可能性がありますのでご注意ください。

どうも、朝からベビースターラーメンをほおばるみやびです。
(メシを食え)

さて、表記の件、実は、けっこう難しくて、長年頭を悩ませていたが、ついに方法を見つけたので、記事に起こしてみた。

例えば、中規模以上のライブラリ、Webアプリケーションを作ったりするときは、だいたいは下記のように、無名関数のスコープ内ないし、名前空間を利用するだろう。(スクリプト汚染を防ぐため)

(function(){
  // 生のJS
})();

$(function(){
  // jQueryだとこれとか
});

(function($){
  $.fn.hoge = function(){
    // jQueryプラグイン内容を定義
  };
})(jQuery);

JavaScriptの性質上、基本一つのファイルで完結することが望ましいが、(他の言語よりスパゲティコードになりやすい)
中~大規模の開発の場合、どうしてもファイル分けをして、これらのスコープ内かつ、グローバル変数を定義したいときがある。
そういう時の技として、下記がある。

(function(){
  window.hoge = 'aaaaa';
})();

windowオブジェクトに関しては、Webブラウザ上で動くJS限定ではあるが、他のプラットホームでも同様のものがあるはず。
とかく、WebブラウザJSに関しては、ルートで変数を定義した場合、全て関数も含め、windowのプロパティ(ざっくり異訳すると子要素)となるため、それを利用して、windowオブジェクトのプロパティとして、変数や関数を定義することによって、グローバルを定義できるのだ。

だが、このやり方だと、
再代入はできるわ、ぶっ壊すこともできるわで、あまり、スコープから定義した意味がなくなってしまう。
だが、constで変数を定義しようとしてもスコープ内の変数となってしまう。
どうすれば、スコープ内からグローバル変数を、定数っぽく、constで定義したような変数にすることができるのか。

Object.freeze()使えばいんじゃね?と思うかもしれないが、
これは実は、あくまでプロパティの凍結を行うだけで、
変数自体の再代入は可能なのだ。

(function(){
  window.hoge = {};
  hoge.mogu = 'ak47';
  Object.freeze(hoge);

  hoge = 25;
  console.log(hoge); // 出力:25
})();

しかし、class構文は、まだ使えるブラウザもそう多くない。
じゃぁ、どうするか。

便利な関数があるんですよ。お兄さん。

(function(){
  Object.defineProperty(window, 'hoge', {writable: false, value: 'akb48'});
})();

この、defineProperty、要は、オブジェクトの定数的なプロパティを生成する関数。
もちろん値だけでなく、関数だって定義できる。(さすがゆるガバスクリプト言語)

(function(){
  Object.defineProperty(window, 'mogu', {writable: false, value: function(){
    // 処理内容
  }});
})();

この、defineProperty、constとほぼ同じ挙動をし、
再代入はできないが、プロパティはいくらでも変更可能というもの。
(というか、const出る前に使われていた関数かもしれない)
プロパティも凍結したかったら、freezeとか、sealを使えばいい。(試してないけど多分イケる)

いやー、オブジェクト指向っぽくなんかかっこいいやり方ないか、探しに探してましたが、まさかこんな方法があったとはね。
でも、class構文がどのブラウザでもできるようになれば、こんないらん苦労しなくていいんだけどね 汗
どうにも、ここら辺の制約緩くてかなわんわ、JSは。

さて今回は、JSの変数に関して熱く語ってきましたが、特にSPAやるときなんかはけっこう使えるテクニックなんじゃないかな、と思います。
また、昨今のJS事情として、Web以外でもけっこう広く使われている傾向にあるので、JS自体もけっこう注目されてるんかなーとか個人的に思っており、これからも勉強していこうと思ってます。

ではまた。

ラグナロクオンライン - メイン

トラックバック(0)

トラックバックURL:

コメントする

ページトップへ戻る