JavaScriptでデータオブジェクト風に

JavaScriptで変数といえば「var」ですが、使用する変数が増えてくると取り扱いが面倒になってきます。
配列などで管理する方法もありますが、一長一短あるかと思います。

そこで、上手い方法はないかと模索していて辿り着いたのが、データオブジェクト風に扱う方法でした。

早速、例として、「名前」、「生年月日」、「年齢」という属性を持つ「人物」というデータオブジェクトを定義してみます。

 

/** 人物 */
function Person() {

    /** 名前 */
    var name = "";
    /** 生年月日 */
    var birthday = "";
    /** 年齢 */
    var age = 0;

    /** 名前を設定する。 */
    this.setName = function (_name) {
        name = _name;
    }

    /** 名前を返却する。 */
    this.getName = function () {
        return name;
    }

    /** 生年月日を設定する。 */
    this.setBirthday = function (_birthday) {
        birthday = _birthday;
    }

    /** 生年月日を返却する。 */
    this.getBirthday = function () {
        return birthday;
    }

    /** 年齢を設定する。 */
    this.setAge = function (_age) {
        age = _age;
    }

    /** 年齢を返却する。 */
    this.getAge = function () {
        return age;
    }

}

prototypeを使って記述していく方法などもあるかと思いますが、本職がJavaなので、
慣れた手触りで使えたら楽ちんだなあという要求から、私は今回の方法に落ち着きました。
setter/getterを介して内部変数にアクセスする、一般的なデータオブジェクトです。
使う時は以下のように。

var person1 = new Person();
person1.setName("山田 太郎");
person1.setBirthday("03/01");
person1.setAge(30);

var person2 = new Person();
person2.setName("山田 一");
person2.setBirthday("08/06");
person2.setAge(8);

person1.getAge();    // 30
person2.getBirthday();    // 08/06
person1.getName();    // 山田 太郎

 

関数にパラメータとして渡すことも出来ますし、

/** 加齢 */
function AddAge(person) {
    person.setAge(person.getAge() + 1);
}

AddAge(person2);
AddAge(person2);

person2.getAge();    // 10

 

なので、こういった使い方も出来ます。

/** 家族 */
function Family() {

    /** 父 */
    var father = null;
    /** 母 */
    var mother = null;
    /** 子供 */
    var child = null;

    /** 父を設定する。 */
    this.setFather = function (_father) {
        father = _father;
    }

    /** 父を返却する。 */
    this.getFather = function () {
        return father;
    }

    /** 母を設定する。 */
    this.setMother = function (_mother) {
        mother = _mother;
    }

    /** 母を返却する。 */
    this.getMother = function () {
        return mother;
    }

    /** 子供を設定する。 */
    this.setChild = function (_child) {
        child = _child;
    }
/** 子供を返却する。 */ this.getChild = function () { return child; } }


「父」、「母」、「子供」という「人物」型の属性を持つ「家族」というデータオブジェクトを作りました。

 

var yamada = new Family();
yamada.setFather(person1);
yamada.setChild(person2);

yamada.getFather().getBirthday();    // 03/01
yamada.getChild().getName();    // 山田 一

 

クラスを継承して新しいクラスを作ることも出来ます。例えば、「家族」に「弟」を追加します。

/** 弟のいる家族 */
function BigFamily() {

    Family.call(this);

    /** 弟 */
    var brother = null;

    /** 弟を設定する。 */
    this.setBrother = function (_brother) {
        brother = _brother;
    }
    /** 弟を返却する。 */
    this.getBrother = function () {
        return brother;
    }

}

var tanaka = new BigFamily();
var person3 = new Person();
person3.setName("田中 花子");
person3.setBirthday("04/04");
person3.setAge(29);

var person4 = new Person();
person4.setName("田中 次郎");
person4.setBirthday("12/23");
person4.setAge(6);

tanaka.setMother(person3);
tanaka.setBrother(person4);

tanaka.getMother().getName();    // 田中 花子
tanaka.getBrother().getName();    // 田中 次郎

 

Javaと違って変数の型の扱いが緩いので、取り扱いには注意しなければいけないのが難点でしょうか。
特に、パラメータで渡す場合など、コンパイルエラー等を出してくれる訳ではないので、
実際に実行される段になってようやくエラーで止まる…ということがよくあります。
パラメータで渡ってきたオブジェクトの型チェックを行いたい場合は、typeofやprototypeを用いて
型を確認するのが良いようです。

// 標準的なオブジェクトの場合はtypeofで
typeof(person3.getName()) == 'string';    // true
typeof(person3.getAge()) == 'string';    // false
typeof(person3.getAge()) == 'number';    // true

// 今回作ったようなオブジェクトはprototypeで
Person.prototype.isPrototypeOf(person3);    // true
Person.prototype.isPrototypeOf(tanaka);    // false
BigFamily.prototype.isPrototypeOf(tanaka);    // true

作り込みバグには気をつけなければいけませんね。