Closed4

【JavaScript TypeScript】クラスのおさらい

shogoooshogooo

TypeScriptやNest.jsを学習していると頻繁にクラスが出てくるので、クラスについての基本をおさらい!

以下のコードはUserクラスをインスタンス化し、nameageプロパティを持つオブジェクトを作成し、変数 user に割り当てるもの。

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
let user = new User("sho", 31);

1. インスタンスの作成
new User(...)Userクラスの新しいインスタンス(オブジェクト)が作成される。
この時点ではインスタンスは空のオブジェクト{ }

2. インスタンスの初期化
constructor(name, age)でインスタンスの初期化が行われる。
ここではインスタンスにnameageプロパティを追加し、それぞれのプロパティに引数で渡された値を割り当てる。

constructor(name, age) {
 this.name = name;
 this.age = age; 
}

3. thisの補足
thisは現在のインスタンスを指すキーワード。
コンストラクタの中でthis.namethis.ageとすると、空だったインスタンスにnameageプロパティが追加される。

イメージ

{ 
  name
  age
}

this.name = name の左辺はインスタンスのプロパティ、右辺は引数を指す。
ここではnameプロパティに引数name('sho')を割り当てることをしている。

まとめ
インスタンスの初期化はコンストラクタで行われ、thisを使って現在のインスタンスにプロパティを追加する。
コンストラクタに引数で渡された値をプロパティに割り当てることで初期化を行う。

{ name: 'sho', age: 31 } 
shogoooshogooo

super()メソッドの使用について。
親クラスを継承したサブクラスの中で、親クラスのコンストラクタを呼び出して初期化するために使用するメソッド。

以下のコードはEmployeeクラスをインスタンス化し、nameageemployeeIdプロパティを持つオブジェクトを作成し、変数employeeに割り当てるもの。

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

class Employee extends User {
  constructor(name, age, employeeId) {
    super(name, age);
    this.employeeId = employeeId;
  }
}

let employee = new Employee("sho", 31, 12345);

1. インスタンスの作成
new Employee(...)Userクラスを継承したEmployeeクラスの新しいインスタンスが作成される。

2. インスタンスの初期化
super(...)で親クラスのコンストラクタを呼び出し実行。
Employeeインスタンスにnameageプロパティにそれぞれの値が設定される。
this.employeeid = employeeIdによってemployeeIdプロパティに引数の値が設定される。
これによりインスタンスの初期化が完了!

class Employee extends User {
  constructor(name, age, employeeId) {
    super(name, age); 
    this.employeeId = employeeId;
  }
}
shogoooshogooo

先ほどのコードをTypeScriptで書き直します。

コード内に以下を付きする必要あり。
クラスの型定義
class ClassName {...}の内部でプロパティの型を定義する。
引数の型定義
constructor(...)の内部で引数の型を定義する。

冗長なコードが完成!
しかし、TypeScriptではもっと短くコードを書くシンタックスが存在します!

before
class User {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

class Employee extends User {
  employeeId: number; 
  constructor(name: string, age: number, employeeId: number) {
    super(name, age);
    this.employeeId = employeeId;
  }
}

let employee = new Employee("sho", 31, 12345);
after
class User {
  constructor(public name: string, public age: number) {}
}

class Employee extends User {
  constructor(name: string, age: number, public employeeId: number) {
    super(name, age);
  }
}

let employee = new Employee("sho", 31, 12345);

ポイント
constructorの引数にアクセス修飾子(public, private, protectedなど)を付ける。そうすると、

  • 自動で引数と同名のプロパティが作成される!
  • 渡された引数で初期化まで行ってくれる!
  • クラス宣言時の型宣言も省略可能!
    constructor(public name: string, public age: number) {}
shogoooshogooo

以下はNest.jsでルーティングの役割を行うコントローラのコードの一部。

コードの概要
MoviesServiceのインスタンスをmoviesServiceプロパティとしてクラスに注入(DI)している。
その後コンストラクタで初期化をすることで、MoviesControllerインスタンスがMoviesServiceの機能を利用可能になる。

constructor(private readonly moviesService: MoviesService) {}
private:クラス内部からしか使えないようにするアクセス修飾子
readonly:読み取り専用にする修飾子

constructor(...) {}MoviesControllerクラスの新しいインスタンスを作成し、MoviesService型moviesServiceプロパティで初期化を行なっている。

movies.controller.ts
@Controller('movies')
export class MoviesController {
  constructor(private readonly moviesService: MoviesService) {}

  @Get()
  async findAll(): Promise<Movie[]> {
    return await this.moviesService.findAll();
  }

@Get()メソッドの中のthisは、
MoviesControllerのインスタンスを示している。
this.moviesService.findAll();とは、
MoviesControllerの現在のインスタンスのmoviesServiceプロパティを通じて、MoviesServiceクラスで定義したfindAll()メソッドを使用する、ということ。

このスクラップは2024/01/24にクローズされました