インスタンス化

インスタンス化

早速、次のサンプルをご確認ください。
personオブジェクトが定義されており、nameとageというプロパティと、greetというメソッドが用意されています。

var person = {
  name: 'Taro',
  age: 22,
  greet: function() {
    return 'My name is Taro. I am 22 years old.'
  }
};

function outputObj_3() {
  console.log(person.greet()); // My name is Taro. I am 22 years old.
}

このオブジェクト同じ構造で、5人分のオブジェクトを用意する必要が出てきた場合はどのようにコーディングすればいいでしょうか?

全てのオブジェクトのプロパティとメソッドを漏れなく記述しようとすると、上記のサンプルのpersonクラスを5つ用意する必要があります。
このpersonクラスを5つも用意するとなると記述する量も多く、助長なスクリプトになってしまいます。
また、オブジェクトの構造やメソッドの内容を変更しなければならなくなった場合、
全てのオブジェクトについて修正を加える必要があり、メンテナンス性にも問題があります。

この問題を解消する手段として、JavaScriptにはオブジェクトの「ひな型」をベースとして、
同じプロパティやメソッドを持つ別のオブジェクトを生成する仕組みがあります。

ここで用語の定義として、それぞれ次のように呼びます。

  • オブジェクトの特性を定義するひな型: クラス
  • クラスを元にしてオブジェクトを生成すること: インスタンス化
  • インスタンス化により生成されたオブジェクト: インスタンス

オブジェクトをスクリプトの部品として捉えると、その再利用性や可読性が高まりますし、
「ひな型」自体に変更を加えないので、オリジナルのオブジェクト構造についての安全性が高まります。

コンストラクタとnew演算子によるインスタンス化

では、クラスを定義してインスタンス化をする方法について順を追って見ていきましょう。
まず、既にクラスが定義されているとして、
そのクラスをインスタンス化するには、以下のように new演算子 を使って記述します。

var 変数名 = new コンストラクタ名(引数1, 引数2, ...);

コンストラクタというのは、クラスをインスタンス化する際に最初に呼び出される関数で、生成したオブジェクトの初期化処理をするという特別な役割を持ちます。
そして、コンストラクタにより初期化されたオブジェクトが変数に代入されます。
コンストラクタは一般の関数と同様で、次のように定義することができます。

var コンストラクタ名 = function(仮引数1, 仮引数2, ...) {
  // 処理
}

コンストラクタ名は、通常の関数名と区別するために先頭を大文字で始めるのが一般的で、これがいわゆるクラス名として使用されます。
また、コンストラクタにはreturn文による戻り値は不要です。
なぜかというと、new演算子によりコンストラクタを呼び出すことで自動的に初期化したオブジェクトが戻るようになるからです。

クラスをインスタンス化するときには、new演算子を使ってインスタンスを初期化する関数であるコンストラクタを呼び出します。

thisキーワード

それでは、コンストラクタ内の処理は具体的にどのようなものでしょうか?
オブジェクトの「ひな型」をインスタンス化したときに、インスタンスに渡すメンバーを定義する必要があります。
その際に使用するのが thisキーワード です。

thisキーワードは生成したインスタンス自体を表します。
そのため、このthisキーワードを用いてインスタンスのメンバーを変更したり、その値を代入することができます。
thisキーワードは次の書式でコンストラク内に記述します。

this.プロパティ名 = ;
this.メソッド名 = function(仮引数1, 仮引数2, ...) {
  // 処理
  return ;
}

コンストラクタ内のthisキーワードは、これから生成されるインスタンス自体を表します。

ここで、コンストラクタとインスタンス化の例として次のサンプルを確認してみましょう。
new演算子によって、Personコンストラクタにnameおよびageを引数として渡して、オブジェクトを生成するものです。
実行後ログを確認すると、渡した引数がthisキーワードによって、それぞれのプロパティにセットされているのが確認できるでしょう。

var Person = function(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    return 'My name is ' + this.name + '. I am ' + this.age + ' years old.'
  };
};

function outputObj_4() {
  var person = new Person('Hanako', '25');
  console.log(person.greet());
}

My name is Hanako. I am 25 years old.

コンストラクタにメンバーを定義するのであれば、クラスとコンストラクタは同一のものと思われるかもしれません。
実際にオブジェクトとしては同一のものを指しますが、厳密には下記のように使い分けられています。

  • インスタンス化の際に最初に呼び出す関数を指す場合はコンストラクタ
  • ひな型を指す場合はクラス

インスタンスのメンバーの変更

クラスから生成したインスタンスはオブジェクトのため、個別にメンバーの値の変更やメンバーの追加も可能です。
次のサンプルを実行してみましょう。ageプロパティの値に5を加算して、jobs プロパティを新たに追加しています。

var Person = function(name, age) {
  this.name = name;
  this.age = age;
};

function outputObj_5() {
  var person = new Person('Nobuo', 20);
  person.age += 5;
  person.jobs = 'Engineer';
  console.log(person);
}

 { name: 'Nobuo', age: 25 , jobs: 'Engineer' }