javascriptの名前空間、モジュールパターン(個人的メモ)
※この記事は、様々なソースをもとに個人的に学んだことを未来の自分が見返す目的で一つにまとめたものです。
2019.12 ES2015に則ってletで変数宣言する場合、グローバル汚染は心配無いようです。 この記事は根本から古い議論になっている可能性があります。
いつもjavascript書いているわけではないので、毎回始動で何かしら躓くので(汗)、そのタイムラグを少しでも短くしようと思い、今後の自分のためにメモっていきます。
目的としては、
- グローバル変数汚染をせずに、変数や関数を体系的に管理できる形で書き進められるよう、パターンを頭に入れること
です。
初歩的なことの復習
2018年当時、javascriptを使い始めたての頃、グローバル変数をたくさん作ってはいけない、ということを覚えました。
javascriptでは、基本的に変数を宣言する場合、
var 変数名;
を指定していました。
(2019.12追記)注意:ES2015以降は、
var
は基本使われなくなったみたいです。普通の変数は、
let
で、定数はconst
で指定するようです。(ほんの最近までvar
使ってました・・・)なので、スコープの概念は、新しい記事で確認してください。
グローバル変数(関数に依らず、プログラム全体で使える変数)は、この var
をつけないで宣言する、または、関数の外で宣言することで生成されます。
var globalParameter = 1; // これはグローバル変数 function myFunction() { var localParameter = 1; // これはローカル変数 globalParameter2 = 2; // これもグローバル変数 }
このグローバル変数の宣言に、なぜ注意が必要かというと、グローバル変数として宣言してしまうということは、プログラム全体で通用するということになるので、自分以外のチームの人が書いたjavascriptで同じ変数を宣言していた場合、かち合って想定通りにプログラムが動かない事態が発生し得ます。
他にも、javascriptはライブラリなどを多用する言語でもありますし、これらですでに使われている変数などを宣言してしまうと、挙動がおかしくなることがあるようです。
ということで、じゃあどうすればいいのよ、というのを調べましたところ、自分のプログラム全体を無名関数で括る
ことで、その中でのみ使える変数とさせる、という手もあるようですが、 名前空間
というのを自分のプログラム専用に立てて、その中でであれば自由にグローバル変数ぽく使える変数を作成できるということがわかりました。
名前空間について、書かれているサイトなどは、得てして中・上級者向けのが多く、またjavascriptの公式は、大した説明が書かれていないということで、ちょっと苦戦しましたが、
基本的に、 グローバル変数を乱用しておかしなことにならないようにする
という目的を達成するためだけであれば、そこまで難しい知識はなくても大丈夫そうでした。
名前空間の基本的な作り方
基本的な名前空間の宣言は、とっても簡単で、以下のようにします。
var myAPP = {};
こうすることで、自分で作る変数や関数を、自分のアプリケーションのなかでのみ通用するものとして、宣言していくことができます。
ただし、最初に宣言するとき、このアプリケーションのネーミングすらも被っているとまずいので、今まで使われていなかったかな? というのを確認して宣言する書き方が以下のようになります。
if ( typeof myApp == 'undefined' ) { var myApp = {}; }
または、以下でも同じことができます。
var myApp = myApp || {};
この時、(おそらく中上級者には当たり前だから、初心者しかこういうことは書かないんだろうなと思うのですが)変数名は大文字でも小文字でもOKでした。
なので、アプリケーション名を、定数っぽく APPLICATION_NAME
とかにすることもできるし、 myApp
とか、 serviceName
とかでもいいわけです。
かつ、アンダースコアでもダッシュ(-)でも、普通に使えました。
この {}
という囲みは、オブジェクトとして扱うという意味のようです。
名前空間もオブジェクト、その中で定義する関数も、変数もオブジェクトということのようなのです。
名前空間内に自分がプログラムで使いたいグローバル変数を宣言する
さて、名前空間を作ったら、次は自分の使いたい変数を作ります。
var myApp.hoge = {};
これでおkです。 この中に連想配列を入れたい場合は、
var myApp.hoge = { key1:1, key2:2, key3:3};
といれればいいですし、ただ値だけを持たせる場合は、
var myApp.hoge = 1;
などと入れればOKでした。
モジュールパターン
少しjavascriptを書く経験をして行くにつれ、だんだんと関数や変数をひとところで拡張性ある形で管理したくなってきました。
参考にしたサイトで、とても綺麗な名前空間・関数・変数の定義の仕方を書いているところがあったので、私も今後は同様の階層構造として自作の関数を整理するようにしようと思います。下記のような感じ。
//(1) 名前空間の準備 var myApp = myApp || { util: { //関数 }, data: { //変数 hoge: 1; } } // (2) モジュールの定義 myApp.util = (function() { // private member buttonClick = function() { alert("ここに関数の中身を入れていきます"); }); getHoge = function() { var hoge = myApp.data.hoge; return hoge; } // public API return { buttonClick: buttonClick, getHoge: getHoge; } })(); // (3) モジュールを使う console.log(myApp.util.getHoge());
知っている人にとってはあまりにも簡単なことなのかと思うのですが、如何せん初めてやる場合、実際に作ってみて、
色々なすでに作ってある関数の中でこの変数を呼び出してみて、 console.log
で中身を確認できたときはホッとしました。
(初心者あるある)
以上。
参考にしたサイト:
https://qiita.com/kenju/items/c7fad62a12cc2809b507
※PDFか電子書籍にまとめられたそうで、このページでは見られなくなっていました。(2019.12追記)