JavaScriptのクラスとインスタンス


はじめに

JavaScriptのクラスとインスタンスの基本について学んだので備忘録としてまとめたいと思います。クラスとインスタンスの知識はReactを扱う際にも必要な知識なので改めてES6から実装された新機能は学ぶべきだと思いました。

オブジェクトとは

クラスとインスタンスに入る前にオブジェクトについておさらいです。
オブジェクトは複数の値をプロパティという名前をつけて管理できる格納庫みたいなものです。

const user = {name: 'アナゴ', sex: 'male'};

# 定数名.プロパティ名で値を取得できます。
console.log(user.name);

またオブジェクトの値には関数を用いることができます。
また、その関数を呼び出すには定数名.プロパティ名()と記述します。
以下のコードでは関数の部分をアロー関数で記述しています。

const user = {
  name: 'アナゴ',
  greet: () => {
    console.log('おはよう');
  }
}
# 関数の呼び出し
user.greet();

オブジェクトを量産したい

Webサービスでは上記のようなオブジェクトをいくつも扱っています。
例えば以下のようにオブジェクトをいくつも作成する場合は毎回ゼロから作成していたらとても手間になります。

そこで効率よくオブジェクトを作成するために設計図を用意し、ぞの設計図を元にデータを作成していきます。
この設計図のことをクラス、一方一つ一つのデータをインスタンスと呼びます。

クラスの定義

まずは設計図であるクラスを定義します。
定義の仕方はclass クラス名です。
ちなみにクラスの命名規則としてはキャメルケース(単語の先頭を大文字にする)が慣例です。

class IsonoFamily {

}

インスタンスの生成

設計図は用意できたので個別のデータを作成します。クラスからオブジェクトを生成にはnew クラス名()と記述します。このクラスから生成したオブジェクトをインスタンスといいます。

class IsonoFamily {
}

// IsonoFamilyクラスのインスタンスを定数namiheiに代入
const namihei = new IsonoFamily();

namiheiというインスタンスはこれで作成できました。しかしクラスの中身に何も記述していないのでインスタンスもカラの状態です。次にクラスに中身を追加していきます。

コンストラクタ

クラスにはコンストラクタという機能が用意されています。
コンストラクタはインスタンスを生成するときに実行したい処理や設定を追加するための機能です。
クラスの中にconstructor() { }と記述し、さらにこのコンストラクタの中に処理を記述します。

class IsonoFamily {
  // コンストラクタを追加
  constructor() {
    console.log('インスタンスを生成しました');
  }

}

const namihei = new IsonoFamily();

プロパティと値を追加

コンストラクタの中で生成したインスタンスに情報を追加します。
this.プロパティ名 = 値と記述することで情報を追加できます。

class IsonoFamily {
  constructor() {

    // ageプロパティを追加
    this.age = 54;
  }
}

const namihei = new IsonoFamily();

// 年齢を出力
console.log(namihei.age);

インスタンスごとに値を変える

現段階のままでは新しくインスタンスを生成してもどれも同じ情報が付与されてしまいます。
これを解決するにはconstructor(age, voiceActor)のようにコンストラクタに引数を渡してあげます。

またインスタンスを生成する際にnew クラス名()()に値を追加します。

class IsonoFamily {
  // 引数に「name」と「age」を追加してください
  constructor(voiceActor, age) {
    // voiceActorを引数として受け取る
    this.voiceActor = voiceActor;

    // ageを引数として受け取る
    this.age = age;
  }
}

// 引数に「"モカ"」と「8」を渡してください
const namihei = new IsonoFamily("茶風林", 54);

console.log(`声優: ${namihei.voiceActor}`);
console.log(`年齢: ${namihei.age}`);

メソッドとは

メソッドとはインスタンスの動作みたいなものです。
メソッドはクラスの中でメソッド名(){ }と記述し定義します。関数とにたようなものなので{ }内に処理を記述していきます。またメソッドを呼び出す際はインスタンス.メソッド名()と記述します。

class IsonoFamily {
  constructor(voiceActor, age) {
    this.voiceActor = voiceActor;
    this.age = age;
  }

  // greetメソッドを追加
  greet() {
    console.log('ばかもん!');
  }

}

const namihei = new IsonoFamily("茶風林", 54);

console.log(`声優: ${namihei.voiceActor}`);
console.log(`年齢: ${namihei.age}`);

// namiheiに対してgreetメソッドを呼びだす
namihei.greet();

メソッド内で値を使う

メソッド内でインスタンスの値を使うにはthis.プロパティ名と記述します。

class IsonoFamily {
  constructor(voiceActor, age) {
    this.voiceActor = voiceActor;
    this.age = age;
  }

  greet() {
    console.log('ばかもん!');
  }

   // infoメソッドを追加
  info() {
    console.log(`声優は${this.voiceActor}です`);
    console.log(`${this.age}歳です`);
  }

}

const namihei = new IsonoFamily("茶風林", 54);

// namiheiに対してgreetメソッドを呼びだす
namihei.greet();

// namiheiに対してinfoメソッドを呼びだす
namihei.info();

メソッド内でメソッドを使う

メソッド内で他のメソッドを呼び出すこともできます。
メソッド内でthis.メソッド名()と記述することで同じクラスの他のメソッドを使うことができます。

class IsonoFamily {
  constructor(voiceActor, age) {
    this.voiceActor = voiceActor;
    this.age = age;
  }

  greet() {
    console.log('ばかもん!');
  }

  info() {
    // greetメソッドを呼びだす
    this.greet();

    console.log(`声優は${this.voiceActor}です`);
    console.log(`${this.age}歳です`);
  }

}

const namihei = new IsonoFamily("茶風林", 54);

namihei.info();

継承

継承とはすでにあるクラスをもとに新しくクラスを作成する方法です。
例えばIsonoFamilyクラスからFugutaFamilyクラスを継承するとIsonoFamilyクラスの全ての機能を引き継いでクラスを生成します。

継承はclass FugutaFamily extends IsonoFamilyと記述します。

class IsonoFamily {
  constructor(voiceActor, age) {
    this.voiceActor = voiceActor;
    this.age = age;
  }

  greet() {
    console.log('ばかもん!');
  }

  info() {
    // greetメソッドを呼びだす
    this.greet();

    console.log(`声優は${this.voiceActor}です`);
    console.log(`${this.age}歳です`);
  }

  // IsonoFamilyクラスを継承してFugutaFamilyクラスを定義
  class FugutaFamily extends IsonoFamily {

  }

}

const namihei = new IsonoFamily("茶風林", 54);

namihei.info();

継承したクラスの特性

FugutaFamilyクラスはIsonoFamilyクラスの全ての機能を引き継いでいます。
なのでFugutaFamilyクラスの中身は空でもIsonoFamilyクラスで定義されているメソッドなどはそのまま使うことができます。

class IsonoFamily {
  constructor(voiceActor, age) {
    this.voiceActor = voiceActor;
    this.age = age;
  }

  greet() {
    console.log('ばかもん!');
  }

  info() {
    // greetメソッドを呼びだす
    this.greet();

    console.log(`声優は${this.voiceActor}です`);
    console.log(`${this.age}歳です`);
  }

  // IsonoFamilyクラスを継承してFugutaFamilyクラスを定義
  class FugutaFamily extends IsonoFamily {

  }

}

// 定数taraにFugutaFamilyクラスのインスタンスを代入
const tara = new FugutaFamily("さすがたかこ", 3);

tara.info();

子クラスにプロパティを追加したい

親クラスで設定したプロパティの他に、子クラスに個別にプロパティを付与させることができます。
その場合は子クラスのコンストラクタの中にsuper()と記述し、その中に親クラスが受け取る引数を記述します。

class IsonoFamily {
  constructor(voiceActor, age) {
    this.voiceActor = voiceActor;
    this.age = age;
  }

  greet() {
    console.log("ばかもん!");
  }

  info() {
    this.greet();
    console.log(`声優は${this.voiceActor}です`);
    console.log(`${this.age}歳です`);
  }
}

class FugutaFamily extends IsonoFamily {
  // constructorを追加
  constructor(voiceActor, age, hairStyle) {
    super(voiceActor, age); {
      this.hairStyle = hairStyle;
    }
  }

  info() {
    this.greet();
    console.log(`声優は${this.voiceActor}です`);
    // 「髪型は〇〇です」と出力
    console.log(`髪型は${this.breed}です`);

    console.log(`${this.age}歳です`);
  }
}

// 3つ目の引数に「"おかっぱ"」を渡す
const tara = new IsonoFamily("さすがたかこ", 3, 'おかっぱ');
tara.info();

以上です!