クラスの扱い方

クラスの扱い方

本記事について

要約

このページでは、JavaScriptのクラスという概念について説明しています。JavaScriptのクラスは、オブジェクト指向プログラミングを可能にする構造です。クラスは設計図のようなもので、そのクラスから生成される各オブジェクト(クラスのインスタンス)が持つべき特性(プロパティ)と行動(メソッド)を定義します。

クラスを作るときは、classキーワードを使って定義します。また、クラス内部にメソッドを定義することもできます。たとえば、クラスのインスタンスが特定のアクションを実行することを指示できます。

また、クラスは継承という概念を使って他のクラスから特性を引き継ぐことができます。これにより、一般的な特性を持つクラス(スーパークラス)を定義し、それを特化した形で再利用する(サブクラスを作る)ことが可能になります。

以上がJavaScriptのクラスについての基本的な説明です。この理解を深めるためには、具体的なコードを書いてみることをおすすめします。

前提

Trailheadの英語版をChatGPT4(以下、ChatGPT)に投げて返ってきた内容を載せています。もともとはTrailheadのみで学習していたのですが、不自然な日本語や、JavaScript初学者に理解しづらい用語・概念を手っ取り早く調べるとためにChatGPTとやり取りしながらの学習に切り替えました。
ChatGPTに聞くとおおよそ同じような答えが返ってきますが、毎回聞くのも手間ですし、用語なども追加で聞いていることもあるので備忘録を兼ねて残します。
僕と同じようなJavaScript初学者の方に参考になれば幸いです。

対象のTrailhead↓
Work with Classes 単元 | Salesforce Trailhead

学習目標

このユニットを終えたら、あなたは次のことができるようになります:

  • ES6以降でのクラスの作成と呼び出し方の違いを説明する。
  • クラスの一般的に使用されるメンバーをリスト化する。
  • 基底クラスと派生クラスの違いを明確に理解する。

クラスのように見えるもの…

ES6以前にJavaScriptでクラスを作成したい場合、プロトタイプを使用して以下のような処理を行いました:

function Animal(name) {
  this.name = name;
}
      
Animal.prototype.printName = function() {
  console.log(this.name);
}

この例では、プロトタイプベースのコンストラクタ関数Animalが作成されています。関数名に大文字の"A"が使われ、引数はthisキーワードに割り当てられます。これが他の開発者にAnimalがただの関数ではないことを知らせる唯一の手がかりです。クラスのインスタンス化とprintName関数の呼び出しは以下のように行います:

let duck = new Animal('duck');
duck.printName();  // "duck"と表示されます

もし他の言語から来たのであれば、あなたはクラスベースの継承に慣れているでしょう。しかし、JavaScriptはそれとは異なる動作をします。JavaScriptが少なくともクラスベースの言語のように見えるようにする試みとして、ES6ではclassキーワードが導入されました。この新しい構文を使用すると、Animalクラスは以下のように定義できます:

class Animal {
  constructor(name) {
    this.name = name;
  }
    
  printName() {
    console.log(this.name);
  }
}  

重要な点は、classキーワードが使用されているにもかかわらず、生成されるオブジェクトは依然として関数であるということです。次のコードを実行すると、コンソールに表示されるのは"type"ではなく"function"となります。

console.log(typeof Animal);  // "function"と表示されます

クラスからインスタンスを生成し、メソッドを使用する方法は、コンストラクタ関数の場合と全く同じです。まあ、ある程度は。ES5のコンストラクタ関数ではnewキーワードはオプショナルでしたが、現在では必

須です。クラスを使用する際にnewキーワードを省略すると、TypeErrorがスローされます。

もう一つの違いは、関数宣言は巻き上げることができるということです。つまり、まだ宣言されていない関数を呼び出すことができます。クラスではこのようなことは許されていません。クラスは、その定義が評価された後でしかアクセスできません。

クラスは以下の種類のメンバーを含むことができます。

メンバー 説明
コンストラクタ コンストラクタは、クラスの新しいインスタンスを作成する際に自動的に実行されます。初期化関数が常に呼び出されることを保証します。これにより、クラスの状態が有効に保たれます。ただし、コンストラクタを作成する必要はありません。もし含まれていない場合、JavaScriptエンジンが空のものを作成します。 constructor(name) {
this.name = name;
}
静的メソッド 静的メソッドはクラスのインスタンスの一部ではなく、インスタンスを参照せずにこれらのメソッドを参照することができます。静的クラスメンバーの概念はES6には新しくありませんが、staticキーワードは新しいです。ES6以前には、静的にしたいメソッドをコンストラクタに置く必要がありました。しかし現在では、クラスのどこでもstaticキーワードを使用して配置できます。 static methodName() {
return ‘something’;
}
プロトタイプメソッド これらのメソッドはstaticキーワードを含まず、インスタンスで参照する必要があります。 printName() {
console.log(this.name);
}
ゲッターとセッター これらのアクセッサ関数はオブジェクトリテラルのように動作し、ES5での動作と同じです。基本的には、プロパティ名の前にgetsetキーワードを置くだけです。セッターなしでゲッターを定義すると、そのプロパティは読み取り専用になります。 get area() {
return this.height * this.width;
}

set area(value) {
this.area = value;
}

覚えておく

べき最も重要なことは、ES6のクラスが伝統的なオブジェクト指向のクラスのように見えるとしても、そうではないということです。新しいclassキーワードがあっても、それらはまだJavaScriptのプロトタイプベースの継承に基づいています。

継承について話すと

継承について触れたので、新しい構文でそれがどのように動作するのか気になるかもしれません。ES6のクラスは継承をずっと簡単で直感的にしています。

クラスには基底クラスと派生クラスの2つのバリエーションがあります。その違いはextendsキーワードにあります。派生クラス(またはサブクラス)にはそれがあり、基底クラスにはありません。例えば、以下のParentという名前の基底クラスを見てみてください。

class Parent {
  constructor(name) {
    this.name = name;
  }
      
  getName() {
    return this.name;
  }
}

あなたがParentクラスの機能を拡張したChildという名前のサブクラスを作成する必要があるとします。それはこんな感じになるかもしれません:

class Child extends Parent {
  constructor(name) {
    super(name);
  }
        
  getMessage() {
    return 'Hello ' + super.getName();
  }
}
      
let someone = new Child('person');
console.log(someone.getMessage());     // "Hello person"と表示されます

このコードをPlayCodeにコピーペーストすると、コンソールには"Hello person"というフレーズが表示されます。Childクラス定義中のextendsキーワードは、それが派生クラスであることを示しています。

また、親のコンストラクタや基底クラスからのメソッド定義を参照することができるsuperキーワードの使用にも注意してください。superキーワードを見たら、あなたは派生クラスにいて、基底クラスを参照していることを知ることができます。

さらに詳しく

  • オブジェクト内でメソッド定義を分離するためにコンマが使用される一方、クラスでは許可されていません。
  • クラスは以下のように式を使用して定義することもできます:
const myAnimal = class Animal {
  constructor(name) {
    this.name = name;
  }
          
  printName() {
    console.log(this.name);
  }
}

printNameメソッドはこのように呼ばれます。

let duck = new myAnimal('duck');
duck.printName();  // "duck"と表示されます
Next Post 前の記事
No Comment
コメントする
comment url