JavaScriptのクラス

0 株式
0
0
0
0

導入

クラスはオブジェクトを作成するためのテンプレートです。データを、そのデータを操作するコードでカプセル化します。JSのクラスはプロトタイプに基づいて構築されますが、クラス固有の構文とセマンティクスもいくつかあります。.

クラスは本質的に「特別な関数」であり、関数式と関数宣言を定義できるのと同様に、クラスはクラス式またはクラス宣言の 2 つの方法で定義できます。.

// Declaration
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
// Expression; the class is anonymous but assigned to a variable
const Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
// Expression; the class has its own name
const Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};

関数宣言と同様に、クラス宣言は匿名にすることも、代入先の変数とは異なる名前にすることもできます。ただし、関数宣言とは異なり、クラス宣言はletやconstと同じデッドゾーンの時間的制約を持ち、解除されていないかのように動作します。.

クラス本体

クラスの本体は、中括弧{}で囲まれた部分です。ここで、メソッドやコンストラクタといったクラスのメンバーを定義します。.

「use strict」ディレクティブがなくても、クラスの本体は厳密モードで実行されます。.

クラス要素は、次の 3 つの側面で特徴付けられます。

  • タイプ: 受信者、規制者、方法、またはフィールド
  • 場所: 静的またはサンプル
  • 表示設定: 公開または非公開

コンストラクタ

コンストラクタメソッドは、クラスで作成されたオブジェクトを作成および初期化するための特別なメソッドです。クラスには「コンストラクタ」という名前の特別なメソッドが1つだけ存在できます。クラスにコンストラクタメソッドのインスタンスが複数存在する場合、SyntaxError がスローされます。.

コンストラクターは、 super キーワードを使用してスーパークラスのコンストラクターを呼び出すことができます。.

コンストラクター内でインスタンス プロパティを作成できます。

class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}

あるいは、インスタンス プロパティの値がコンストラクター引数に依存しない場合は、それらをクラス フィールドとして定義できます。.

静的初期化ブロック

静的ブロックを使用すると、初期化中に式を評価するなど、静的プロパティの柔軟な初期化が可能になり、プライベート スコープへのアクセスも許可されます。.

複数の静的ブロックを宣言することができ、これらのブロックの間に静的フィールドおよびメソッドの宣言を散在させることができます (すべての静的項目は宣言順に評価されます)。.

方法

メソッドはクラスの各インスタンスのプロトタイプ上で定義され、すべてのインスタンスで共有されます。メソッドは、単純な関数、非同期関数、ジェネレータ関数、または非同期ジェネレータ関数のいずれかです。詳細については、「メソッド定義」を参照してください。.

class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
*getSides() {
yield this.height;
yield this.width;
yield this.height;
yield this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
console.log([...square.getSides()]); // [10, 10, 10, 10]

静的メソッドとフィールド

static キーワードは、クラスの静的メソッドまたはフィールドを定義します。静的プロパティ(フィールドとメソッド)は、各インスタンスではなく、クラス自体に定義されます。静的メソッドは、アプリケーションのユーティリティ関数を作成するためによく使用され、静的フィールドは、キャッシュ、固定設定、またはインスタンス間で繰り返し使用される必要のないその他のデータに役立ちます。.

class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = "Point";
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined
console.log(Point.displayName); // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755

現場アナウンス

クラス フィールド宣言構文を使用すると、コンストラクターの例は次のように記述できます。

class Rectangle {
height = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}

クラスフィールドは変数ではなくオブジェクトのプロパティのようなものなので、constなどのキーワードを使って宣言する必要はありません。JavaScriptでは、プライベートプロパティは特別な識別子構文を使用するため、publicやprivateなどの修飾子キーワードも使用すべきではありません。.

上で示したように、フィールドはデフォルト値の有無にかかわらず宣言できます。デフォルト値のないフィールドはデフォルトでは定義されません。フィールドを事前に宣言することで、クラス定義のドキュメントがより明確になり、フィールドが常に存在するため、最適化に役立ちます。.

詳細については、パブリック クラス フィールドを参照してください。.

私有財産

プライベート フィールドを使用すると、定義を次のように変更できます。.

class Rectangle {
#height = 0;
#width;
constructor(height, width) {
this.#height = height;
this.#width = width;
}
}

クラス外からプライベートフィールドを参照するのは誤りです。プライベートフィールドはクラス本体内からのみ読み書き可能です。クラス外からは参照できないものを定義することで、クラスのユーザーがバージョンごとに変更される可能性のある内部構造に依存しないようにすることができます。.

プライベートフィールドは、フィールド宣言で事前に宣言する必要があります。通常のプロパティのように、後から代入によって作成することはできません。.

詳細については、「私有財産」を参照してください。.

継承

extends キーワードは、クラス宣言またはクラス式で使用され、別のコンストラクター (クラスまたは関数) の子としてクラスを作成します。.

class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog("Mitzie");
d.speak(); // Mitzie barks.

サブクラスにコンストラクタがある場合、それを使用する前にまず super() を呼び出す必要があります。super キーワードは、スーパークラスに関連するメソッドを呼び出す場合にも使用できます。.

class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(`${this.name} roars.`);
}
}
const l = new Lion("Fuzzy");
l.speak();
// Fuzzy makes a noise.
// Fuzzy roars.

評価順序

クラス宣言またはクラス式が評価されるとき、そのさまざまなコンポーネントは次の順序で評価されます。

  1. 展開された節(存在する場合)が最初に評価されます。展開された節は有効なコンストラクタ関数またはnullに評価される必要があります。そうでない場合は、TypeErrorがスローされます。.
  2. コンストラクタメソッドが抽出され、コンストラクタが存在しない場合はデフォルトの実装に置き換えられます。ただし、コンストラクタ定義は単なるメソッド定義であるため、このステップは目に見えません。.
  3. クラス要素のプロパティキーは、宣言された順に評価されます。プロパティキーが評価されると、その値で評価された式は、クラスを囲むこの値(クラス自体ではありません)に設定されます。プロパティ値はまだ評価されていません。.
  4. メソッドとアクセサは宣言順にインストールされます。インスタンスメソッドとアクセサは現在のクラスのプロトタイププロパティにインストールされ、静的メソッドとアクセサはクラス自体にインストールされます。プライベートインスタンスメソッドとアクセサは、後でインスタンスに直接インストールするために予約されています。このステップは目に見えません。.
  5. クラスは、拡張機能によって指定されたプロトタイプとコンストラクタによって指定された実装で初期化されます。上記のすべてのステップにおいて、評価された式がクラス名にアクセスしようとすると、クラスがまだ初期化されていないため、ReferenceError がスローされます。.
  6. クラス要素の値は宣言順に評価されます。
  • 各インスタンスフィールド(publicまたはprivate)には、その初期化式が保存されます。初期化式は、インスタンスの作成時、コンストラクタの開始時(基底クラスの場合)、または super() 呼び出しが戻る直前(派生クラスの場合)に評価されます。.
  • 各定数フィールド (パブリックまたはプライベート) について、このセットによる初期化がクラス自体に評価され、クラスにプロパティが作成されます。.
  • 静的初期化ブロックは、クラス自体のこのセットを使用して評価されます。.

これをインスタンスメソッドと静的メソッドに接続する

静的メソッドまたはインスタンスメソッドが値を指定せずに呼び出された場合(例えば、メソッドを変数に代入してから呼び出す場合など)、メソッド内では値は未定義になります。クラス本体内のコードは常に厳密モードで実行されるため、「using strict」ディレクティブがない場合でも同様の動作となります。.

class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined
Animal.eat(); // class Animal
const eat = Animal.eat;
eat(); // undefined

非厳密なケースで上記を従来の関数ベースの構文で書き直すと、this メソッドの呼び出しは自動的に globalThis に制限されます。厳密なケースでは、this の値は未定義のままです。.

function Animal() {}
Animal.prototype.speak = function () {
return this;
};
Animal.eat = function () {
return this;
};
const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)
const eat = Animal.eat;
eat(); // global object (in non-strict mode)
コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

あなたも気に入るかもしれない