ちょっと便利なJavascriptオブジェクトの作り方

今回は、ちょっと便利なJavascriptオブジェクトの作り方をご紹介します。いわゆるモジュール・パターンと呼ばれている方法です。

はじめに

最近、HTML5への注目と共に、Javascriptを使用する機会が増えてきました。以下のように適用範囲は多岐に渡っています。

  • 通常のWebサイトでのユーザビリティ向上
  • スマートフォン用Webサイト開発
  • HTML5アプリによるクライアント・アプリ開発
  • スマートフォンのハイブリッドアプリ開発
  • Node.jsによるサーバサイド・プログラミング

このように、Javascriptが基幹となる仕組みが広がっています。クライアント側とサーバ側を同じ言語で作れることは、開発側にとってはとても有難いことです(学習コストの低減、人的リソース配分の柔軟性など)。もちろん、発注者やエンドユーアにとっても開発速度などの面で利益が生まれます。

Javascriptプログラミングを行う上で必須なのが、オブジェクトの作り方と活用です。従来、Javascriptといえばグローバル変数や関数を多用したプログラミングがなされていました。しかし今日では、Javascriptの使い方も洗練されてきており、オブジェクトを中心としたコードが一般的です。今後、Javascriptの開発をするには、オブジェクトの作り方・使い方について詳しく知る必要があります。

オブジェクト・リテラル

一番簡単な作り方は、いわゆるオブジェクト・リテラルです。ハッシュ形式でオブジェクトを定義する方法です。


var Person = {
  name: 'kazushi',
  age : 36,
  
  init: function() {
    // 何らかの処理
  },
  
  getName: function() {
    return this.name;
  },
  
  getAge: function() {
    return this.age;
  },
  
  // オブジェクト内部でしか使わないメソッド
  doSomething: function() {
    ...
  }
};
// 初期化を実行
Person.init();

この方法は非常に簡単な反面、全てのプロパティを外部から変更可能です。例えば、


Person.name = 'hoge hoge';
Person.age = 0;

などと、プロパティの値を保障できなくなります。また、doSomething()メソッドを外部から実行できてしまいます。複数人での開発などでは意図しないバグを発せさせかねません。また、影響範囲を明確に定義できない問題があります。そのため、保守性が下がってしまいます。さらに、再利用時には、どのメソッドを使用すべきか迷うことも多々あります。

モジュール・パターン

モジュール・パターンはオブジェクトリテラルより断然お勧めです。プライベートメンバや公開API設定などが容易だからです(リテラルなど通常の作り方の場合、Javascriptではスコープ定義が難しいんですね)。

このパターンでは即時関数を利用します。Javascriptでは即時関数と言って、無名関数をその場で実行する方法があります。例えば、次のように記述します。


(function() {
  var i;
  
  for (i=0; i<10; i++) {
    // 何らかの処理
  }
}());

Javascriptのコードが読み込まれた際に、実行されます。何が便利かというと、変数のスコープを限定し(Javascriptでは変数のスコープが関数単位)、影響範囲を狭めることができます。コードが長くなる際には必須の仕組みです。

この即時関数を利用することで、オブジェクトのプライベートメンバ・メソッドや公開API設定を実施します。


var Person = (function(){
  var _name = 'kazushi',
      _age = 36;
  
  function _init() {
    // 何らかの処理
  }
  
  function _getName() {
    return _name;
  }
  
  function _getAge() {
    return _age;
  }
  
  function _doSomething() {
    ...
  }
  
  // 初期化を実行する
  _init();
  
  // 公開APIを返す
  return {
    getName: _getName,
    getAge : _getAge
  };
}());

ポイントは、即時関数内に変数と関数を定義し、最後に公開するものだけをオブジェクトで返している点です。こうすることで、_nameと_ageは外部から変更不可能となります。そして、Personオブジェクトの公開APIを設定でき、設計者の意図通りにこのオブジェクトを制限できます。ここでは_doSomething()関数を外部から実行することはできません。言葉を変えると、使う側は何を使えば良いかをすぐに理解できます。

また、公開APIの変更も簡単です(最後にreturnで返すオブジェクトを変更するだけですね)。

問題点としては、読み込まれた時点でスクリプトが実行される点です。巨大なオブジェクトや複雑な計算を即時関数内に入れて、実行してしまうと時間が掛かります。同時にメモリも消費します。とはいえ、よほどおかしなことをしない限り、実際には大した問題にはなりません。

おわりに

即時関数を用いたJavascriptオブジェクトの作り方は、他にもいろいろとあります。多くのフレームワークでは、即時関数内でオブジェクトを定義し、必要なものだけをwindowオブジェクトのプロパティに追加する方法を使用しています。ちょっとした工夫で、Javascriptをより楽しく便利につかうことは十分可能です。ぜひ試してみて下さい。