JavaScriptはプロトタイプ継承を使用します:すべてのオブジェクトは、そのプロトタイプオブジェクトからプロパティ

JavaやSwiftなどの言語で使用されるオブジェクトを作成するための青写真としての伝統的なクラスは、JavaScriptには存在しません。 プロトタイプの継承はオブジェクトのみを扱います。

プロトタイプの継承は、クラシックなクラスの継承をエミュレートできます。 従来のクラスをJavaScriptに持ち込むために、ES2015標準ではclass構文が導入されています。,

この投稿では、クラスの定義、インスタンスの初期化、フィールドとメソッドの定義、プライベートフィールドとパブリックフィールドの理解、静的フィールドと

1. 定義:クラスキーワード

特別なキーワードclassJavaScriptでクラスを定義します:

class User { // The body of class}

上記のコードはクラスUser。 中括弧{ }はクラス本体を区切ります。 この構文はクラス宣言という名前です。,

クラス名を指定する義務はありません。 クラス式を使用すると、クラスを変数に割り当てることができます。

const UserClass = class { // The body of class};

ES2015モジュールの一部としてクラスを簡単にエクスポートできます。 デフォルトのエクスポートの構文は次のとおりです。

export default class User { // The body of class}

と名前付きエクスポート

export class User { // The body of class}

クラスのインスタンスを作成するときにクラスが便利になります。 インスタ,

new演算子は、JavaScriptでクラスをインスタンス化します。instance = new Class()

たとえば、Userクラスをnew演算子を使用してインスタンス化できます。

const myUser = new User();

new User()クラス。

2. 初期化:constructor()

constructor(param1, param2, ...)は、インスタンスを初期化するクラスの本体の特別なメソッドです。, これは、フィールドの初期値を設定する場所、またはあらゆる種類のオブジェクト設定を行う場所です。

次の例では、コンストラクタはフィールドの初期値を設定しますname:

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

Userのコンストラクタには、フィールドの初期値を設定するために使用されるパラメータnameがあります。this.name.

コンストラクタ内this値は新しく作成されたインスタンスと同じです。,

クラスをインスタンス化するために使用される引数は、コンストラクタのパラメータになります。

class User { constructor(name) { name; // => 'Jon Snow' this.name = name; }}const user = new User('Jon Snow');

nameコンストラクタ内のパラメータには、'Jon Snow'という値があります。

クラスのコンストラクターを定義しない場合は、デフォルトのコンストラクターが作成されます。 デフォルトのコンストラクタは空の関数で、インスタンスは変更されません。

同時に、JavaScriptクラスは一つのコンストラクタまで持つことができます。

3. フィールド

クラスフィールドは、情報を保持する変数です。, フィールドは2つのエンティティにアタッチできます。

  1. クラスインスタンスのフィールド
  2. クラス自体のフィールド(別名static)

フィールドには2つのレベルのアクセシビリティがあります。

  1. Public:フィールドはどこでもアクセス可能です。
  2. Private:フィールドはクラスの本体内でのみアクセス可能です。

3.1Publicインスタンスフィールド

もう一度見てみましょう。前のコードスニペット:

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

this.name = nameインスタンスフィールドnameを作成し、初期値を割り当てます。,

後で、プロパティアクセサを使用してnameフィールドにアクセスできます。

const user = new User('Jon Snow');user.name; // => 'Jon Snow'

nameは、Userクラス本体の外でアクセスできるため、パブリックフィールドです。

前のシナリオのように、コンストラクタ内でフィールドが暗黙的に作成されると、フィールドリストを把握するのが難しくなる可能性があります。 コンストラクタのコードからそれらを解読する必要があります。

より良いアプローチは、クラスフィールドを明示的に宣言することです。, どんなコンストラクタは、インスタンスは常に同じ設定します。

クラスフィールドプロポーザルでは、クラスの本体内のフィールドを定義できます。 さらに、初期値をすぐに指定できます。

class SomeClass { field1; field2 = 'Initial value'; // ...}

Userクラスを変更し、パブリックフィールドを宣言しましょうname:

class User { name; constructor(name) { this.name = name; }}const user = new User('Jon Snow');user.name; // => 'Jon Snow'

name;クラスの本体内でパブリックフィールドnameを宣言します。,

このような方法で宣言されたパブリックフィールドは表現力豊かです:フィールド宣言を簡単に見ると、クラスのデータ構造を理解するのに十分です。

さらに、クラスフィールドは宣言時にすぐに初期化することができます。

class User { name = 'Unknown'; constructor() { // No initialization }}const user = new User();user.name; // => 'Unknown'

name = 'Unknown'クラス本体内でフィールドnameを宣言し、値'Unknown'で初期化します。

パブリックフィールドのアクセスや更新に制限はありません。, 読んで値を割り当て公共分野のコンストラクタ、方法、内外のクラスです。

3.2プライベートインスタンスフィールド

カプセル化は、クラスの内部詳細を隠すことができる重要な概念です。 カプセル化されたクラスを使用するユーザーは、クラスが提供するパブリックインターフェイスにのみ依存し、クラスの実装の詳細には結合しません。

カプセル化を念頭に置いて編成されたクラスは、実装の詳細が変更されたときに更新する方が簡単です。,

オブジェクトの内部データを非表示にする良い方法は、プライベートフィールドを使用することです。 これらは、それらが属するクラス内でのみ読み取りおよび変更できるフィールドです。 外の世界のクラス変更はできませんので、民間分野です。

プライベートフィールドは、クラスの本体内でのみアクセスできます。

フィールド名の前に特別なシンボル#を付けてプライベートにします(例:#myField)。, プレフィックス#は、フィールドを操作するたびに保持する必要があります:宣言、読み取り、または変更します。

インスタンスの初期化時にフィールド#nameを一度設定できるようにしましょう。

#nameはプライベートフィールドです。 アクセスして変更できます#nameの本体内User。 メソッドgetName()(次のセクションのメソッドの詳細)は、プライベートフィールド#nameにアクセスできます。, しかし、プライベートフィールドにアクセスしようとすると#nameUserクラス本体の外側で、構文エラーがスローされます:SyntaxError: Private field '#name' must be declared in an enclosing class

3.3パブリック静的フィールド

クラス自体にフィールドを定義することもできます:静的フィールド。 これらのものを定義するクラスの定数や店舗の情報を特定のクラスです。

JavaScriptクラスで静的フィールドを作成するには、特別なキーワードstaticの後にフィールド名static myStaticFieldを使用します。,

新しいフィールドを追加しましょうtypeユーザータイプを示します:adminまたはregular。 静的フィールドTYPE_ADMINおよびTYPE_REGULARは、ユーザータイプを区別するための便利な定数です。

static TYPE_ADMINおよびstatic TYPE_REGULARUserクラス内で静的変数を定義します。 静的フィールドにアクセスするには、クラスの後にフィールド名を使用する必要があります。User.TYPE_ADMINおよびUser.TYPE_REGULAR

3.,4Private static fields

静的フィールドでさえ、非表示にしたい実装の詳細であることがあります。 この点で、静的フィールドを非公開にすることができます。

静的フィールドをプライベートにするには、フィールド名の前に#特殊記号static #myPrivateStaticFieldを付けます。 たとえば、Userクラスのインスタンス数を制限したいとします。,

静的フィールドUser.#MAX_INSTANCES許可されるインスタンスの最大数を設定し、User.#instances静的フィールドは実際のインスタンス数をカウントします。静的フィールドは、インスタンスの実際の数をカウントします。静的フィールドは、インスタンスの実際の数をカウントします。

これらのプライベート静的フィールドは、Userクラス内でのみアクセスできます。 外部の世界からの何も制限メカニズムに干渉することはできません:それはカプセル化の利点です。

4. メソッド

フィールドにはデータが保持されます。, しかし、データを変更する機能は、クラスの一部である特別な関数、すなわちメソッドによって実行されます。

JavaScriptクラスは、インスタンスと静的メソッドの両方をサポートします。

4.1インスタンスメソッド

インスタンスメソッ インスタ,

たとえば、getName()Userclass:

クラスメソッド内およびコンストラクタ内で、this値はクラスインスタンスと等しくなります。 使用thisインスタンスデータにアクセスするには:this.field、または他のメソッドを呼び出すことも:this.method()。,

新しいメソッドを追加しましょうnameContains(str)一つのパラメータを持ち、別のメソッドを呼び出します:

nameContains(str) { ... }User一つのパラメータを受け入れるクラスstr。 それ以上に、インスタンスの別のメソッドを実行しますthis.getName()ユーザーの名前を取得します。

メソッドはプライベートにすることもできます。 メソッドのプライベートプレフィックスに名前を#にするには。

作ってみましょうgetName()メソッドプライベート:

#getName()プライベートメソッドです。, メソッド内nameContains(str)あなたは次のようにプライベートメソッドを呼び出します:this.#getName()

プライベートであるため、#getName()Userクラス本体の外部で呼び出すことはできません。

4.2ゲッターとセッター

ゲッターとセッターは通常のフィールドを模倣しますが、フィールドへのアクセスと変更方法をより詳細に制御します。

getterはフィールド値を取得しようとしたときに実行され、setterは値を設定しようとしたときに実行されます。,

nameUserのプロパティを空にできないようにするには、プライベートフィールド#nameValueをゲッターとセッターでラップしましょう。

get name() {...}フィールドの値にアクセスするとゲッターが実行されます。user.name.

4.3静的メソッド

静的メソッドは、クラスに直接アタッチされた関数です。 これらは、クラスのインスタンスではなく、クラスに関連するロジックを保持します。,

静的メソッドを作成するには、特別なキーワードstaticの後に通常のメソッド構文static myStaticMethod() { ... }を使用します。

静的メソッドを操作する場合、覚えておくべき2つの簡単なルールがあります。

  1. 静的メソッドは静的フィールドにアクセスできます。
  2. 静的メソッドはインスタンスフィールドにアクセスできません。

たとえば、特定の名前を持つユーザーがすでに取得されているかどうかを検出する静的メソッドを作成しましょう。,

isNameTaken()は、静的プライベートフィールドUser.#takenNamesを使用して取得された名前をチェックする静的メソッドです。

5. 継承:extends

JavaScriptのクラスは、extendsキーワードを使用した単一継承をサポートしています。

式のclass Child extends Parent { }ChildクラスはParentコンストラクタ、フィールド、およびメソッドを継承します。

たとえば、親クラスContentWriterを拡張する新しい子クラスUserを作成しましょう。,

ContentWriterUserコンストラクタ、メソッドgetName()およびフィールドnameから継承します。 同様に、ContentWriterクラスは新しいフィールドpostsを宣言します。

親クラスのプライベートメンバーは子クラスに継承されないことに注意してください。

5.1Parent constructor:super()in constructor()

子クラスで親コンストラクタを呼び出す場合は、子コンストラクタで使用できるsuper()特殊関数を使用する必要があります。,

たとえば、ContentWriterコンストラクタを作成しましょうUserの親コンストラクタを呼び出し、投稿フィールドを初期化します。

super(name)子クラス内ContentWriter親クラスのコンストラクタを実行しますUser.

子コンストラクタ内では、super()を使用する前にthisキーワードを実行する必要があることに注意してください。 super()を呼び出すと、親コンストラクターがインスタンスを初期化することが確認されます。,

class Child extends Parent { constructor(value1, value2) { // Does not work! this.prop2 = value2; super(value1); }}

5.2親インスタンス:メソッド内のスーパー

子メソッド内の親メソッドにアクセスしたい場合は、特別なショートカットsuper

getName()子クラスのContentWriterメソッドにアクセスしますsuper.getName()親クラスから直接User

この機能はメソッドオーバーライドと呼ばれます。

親の静的メソッドにアクセスするには、静的メソッドでもsuperを使用できることに注意してください。

6., Object type checking: instanceof

object instanceof Class is the operator that determines if object is an instance of Class.

Let’s see instanceof operator in action:

user is an instance of User class, user instanceof User evaluates to true.

The empty object {} is not an instance of User, correspondingly obj instanceof User is false.,

instanceofポリモーフィックです:演算子は親クラスのインスタンスとして子を検出します。

writer子クラスContentWriterのインスタンスです。 演算子writer instanceof ContentWriterは、trueと評価されます。

同時にContentWriterUserの子クラスです。 したがって、writer instanceof Usertrue同様に評価されます。

インスタンスの正確なクラスを決定したい場合はどうすればよいですか?, constructorプロパティを使用して、クラスと直接比較できます。

writer.constructor === ContentWriter; // => truewriter.constructor === User; // => false

7。 クラスとプロトタイプ

JavaScriptのクラス構文は、プロトタイプの継承から抽象化するのに素晴らしい仕事をしていると言わなければなりません。 class構文を記述するために、私はプロトタイプという用語を使用していません。

しかし、クラスはプロトタイプ継承の上に構築されています。 すべてのクラスは、インスタンスメソッドを呼び出しコンストラクタです。

次の二つのコードスニペットは同等です。,

クラスversion:

プロトタイプを使用したバージョン:

クラス構文は、JavaまたはSwift言語の古典的な継承メカニズムに精通していれば、作業が簡単です。

とにかく、JavaScriptでクラス構文を使用している場合でも、プロトタイプの継承を十分に把握することをお勧めします。

8. クラス機能の可用性

この記事で紹介したクラス機能は、ES2015とステージ3の提案に広がっています。,

2019年の終わりには、クラスの機能は次のように分割されます。

  • Publicインスタンスフィールドとprivateインスタンスフィールドはクラスフィールドの一部proposal
  • Privateインスタンスメソッドとアクセサはクラスprivateメソッドの一部proposal
  • Publicおよびprivate静的フィールドとprivate静的メソッドはクラスstatic機能の一部proposal
  • 残りはES2015標準の一部です。

9. 結論

JavaScriptクラスは、コンストラクタでインスタンスを初期化し、フィールドとメソッドを定義し, staticキーワードを使用して、クラス自体にもフィールドとメソッドをアタッチできます。

継承はextendsキーワード:親から子クラスを簡単に作成できます。 superキーワードは、子クラスから親クラスにアクセスするために使用されます。

カプセル化を利用するには、フィールドとメソッドをプライベートにして、クラスの内部詳細を非表示にします。 プライベートフィールドおよびメソッド名は、#で始まる必要があります。,

JavaScriptのクラスはますます便利になります。

#を使用してプライベートプロパティの接頭辞を付けることについてどう思いますか?