hagino3000's blog

平成アーカイブス (更新停止)

Javaプログラマが始める、JavaScriptでオブジェクト指向プログラミング入門 その1

John Resigの教材に触発されたので書いてみる。
私自身、Javaオブジェクト指向は理解していても、JavaScriptのnewやprototypeプロパティの意味を理解しないでコードを書いていた時期があったので。JavaはわかるけどJavaScriptでクラスの作り方がいまいちわからない、という人向け。あと自分の中で知識のおさらいとして一旦まとめて書き出してみたかったので。

はじめに 〜クラスってなんぞ?〜

JavaScriptでクラスといっても「クラス」の厳格な定義はありません。以降の文面で「クラス」の意味はJavaで言うクラスに近いものとお考えください。データ(フィールド変数)と機能(メソッド)をまとめたものです。

クラスの種類で書き方が異なってきますので、Javaっぽく4つに分類したものをここで定義します。Java脳で理解できるような説明を入れました。

1.定数クラス

メソッドを持たない定数のみのクラス。全てのフィールドが

public static final String HOGEHOGE = "hogehoge";

みたいな奴とか。

2.インスタンス化しないで使うクラス

全てのメソッドがstaticで定義されているようなユーティリティクラスのイメージ。public class StringUtilsとかそんなのよくありますね。

3.唯一のインスタンスしか作らないクラス

インスタンスを一個だけ作って使いまわすタイプ。シングルトン(singleton)と言えばわかりやすいでしょうか。HttpServletを継承したクラスもそんな使われ方ですね。

4.インスタンスが複数作られるクラス

JavaBeanとかそんな感じ。何個もインスタンスが作られることが前提のクラス。

さっそく見てみよう!

細かいところの説明はかなり省きます。大体の雰囲気が伝わればいいかな、と。サンプルコードはそのままシェルに貼り付けると動く*1ので、試しながら読むとより理解が深まるはず。

定数クラスっぽいもの

//sample 1.1

var System = {
  VERSION : '1.2.1',
  MODE : 'StandAlone',
  BUILD_NO : 345678
}

print('System version is '+ System.VERSION);
print('Mode:'+System.MODE);
print('Build No:' + System.BUILD_NO);


var DefaultStyle = {
  backgroundColor : '#777777'
}

document.body.style.backgroundColor = DefaultStyle.backgroundColor;

現在のJavascriptだとfinal修飾子が無いので、定数のつもりで定義していても変更される可能性があります。厳密にfinalまで再現しようとすると別の書き方をしなければなりません。(後述)

インスタンス化しないで使うクラスっぽいもの

まずは20世紀ライクなサンプル
//sample 2.1

/* ここからフォーム制御関連処理 */
var formId = 'searchForm';
function doSubmit(){
  var f = document.getElementById(formId);
  f.submit();
}
function disableButton(){
  var f = document.getElementById(formId);
  f.btnSubmit.disabled = true;
}
function doHoge(foo){
  alert('This is doHoge:' + foo);
}
/* ここまでフォーム制御関連処理 */

doHoge('test');
名前を付けて、機能ごとに処理をまとめると
//sample 2.2

/**
 * FormControl
 *
 * フォーム制御関連処理
 *
 * 使い方:
 *   FormControl.doSubmit();
 *   FormControl.disableButton();
 *   FormControl.doHoge(foo);
 *
 * @static
 */
var FormControl = {
  formId : 'searchForm',

  doSubmit : function(){
    var f = document.getElementById(formId);
    f.submit();
  },
  disableButton : function(){
    var f = document.getElementById(formId);
    f.btnSubmit.disabled = true;
  },
  doHoge : function(foo){
    alert('This is doHoge:' + foo);
  }
};


// 呼び出し
FormControl.doHoge('test2');

Javaにはパッケージというものがあります。クラス名の衝突を避けるために名前空間を別けるしくみですが、JavaScriptでもそれに似た事ができます。上記サンプルではFormControlという名前のオブジェクトの中に関数(function)を定義しています。こうする事で同じ名前の関数が再定義されてしまうことが避けられます。JavaScriptでは、同じ名前の関数が再定義されると単純に上書きされるだけなので、意図しない関数の上書きをやってしまう事があります。
ちなみにsample 1.1の方では formId, doSubmit, disableButton, doHoge の4つのグローバルシンボルが定義されていますが、sample 1.2の方だとFormControlという一つのグローバルシンボルのみとなります。大規模開発では、グローバルシンボルの使用を最小限に抑えないと大変なことになります。


つづく
次の2つは次のエントリか、このエントリに追記します
・唯一のインスタンスしか作らないクラス
インスタンスが複数作られるクラス

*1:Firefoxでのみ動作確認