JavaScriptはプロトタイプ継承を使用します:すべてのオブジェクトは、そのプロトタイプオブジェクトからプロパティ
JavaやSwiftなどの言語で使用されるオブジェクトを作成するための青写真としての伝統的なクラスは、JavaScriptには存在しません。 プロトタイプの継承はオブジェクトのみを扱います。
プロトタイプの継承は、クラシックなクラスの継承をエミュレートできます。 従来のクラスをJavaScriptに持ち込むために、ES2015標準ではclass
構文が導入されています。,
この投稿では、クラスの定義、インスタンスの初期化、フィールドとメソッドの定義、プライベートフィールドとパブリックフィールドの理解、静的フィールドと
1. 定義:クラスキーワード
特別なキーワードclass
JavaScriptでクラスを定義します:
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つのエンティティにアタッチできます。
- クラスインスタンスのフィールド
- クラス自体のフィールド(別名static)
フィールドには2つのレベルのアクセシビリティがあります。
- Public:フィールドはどこでもアクセス可能です。
- 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
にアクセスできます。, しかし、プライベートフィールドにアクセスしようとすると#name
User
クラス本体の外側で、構文エラーがスローされます: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_REGULAR
User
クラス内で静的変数を定義します。 静的フィールドにアクセスするには、クラスの後にフィールド名を使用する必要があります。User.TYPE_ADMIN
およびUser.TYPE_REGULAR
。
3.,4Private static fields
静的フィールドでさえ、非表示にしたい実装の詳細であることがあります。 この点で、静的フィールドを非公開にすることができます。
静的フィールドをプライベートにするには、フィールド名の前に#
特殊記号static #myPrivateStaticField
を付けます。 たとえば、User
クラスのインスタンス数を制限したいとします。,
静的フィールドUser.#MAX_INSTANCES
許可されるインスタンスの最大数を設定し、User.#instances
静的フィールドは実際のインスタンス数をカウントします。静的フィールドは、インスタンスの実際の数をカウントします。静的フィールドは、インスタンスの実際の数をカウントします。
これらのプライベート静的フィールドは、User
クラス内でのみアクセスできます。 外部の世界からの何も制限メカニズムに干渉することはできません:それはカプセル化の利点です。
4. メソッド
フィールドにはデータが保持されます。, しかし、データを変更する機能は、クラスの一部である特別な関数、すなわちメソッドによって実行されます。
JavaScriptクラスは、インスタンスと静的メソッドの両方をサポートします。
4.1インスタンスメソッド
インスタンスメソッ インスタ,
たとえば、getName()
User
class:
クラスメソッド内およびコンストラクタ内で、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は値を設定しようとしたときに実行されます。,
name
User
のプロパティを空にできないようにするには、プライベートフィールド#nameValue
をゲッターとセッターでラップしましょう。
get name() {...}
フィールドの値にアクセスするとゲッターが実行されます。user.name
.
4.3静的メソッド
静的メソッドは、クラスに直接アタッチされた関数です。 これらは、クラスのインスタンスではなく、クラスに関連するロジックを保持します。,
静的メソッドを作成するには、特別なキーワードstatic
の後に通常のメソッド構文static myStaticMethod() { ... }
を使用します。
静的メソッドを操作する場合、覚えておくべき2つの簡単なルールがあります。
- 静的メソッドは静的フィールドにアクセスできます。
- 静的メソッドはインスタンスフィールドにアクセスできません。
たとえば、特定の名前を持つユーザーがすでに取得されているかどうかを検出する静的メソッドを作成しましょう。,
isNameTaken()
は、静的プライベートフィールドUser.#takenNames
を使用して取得された名前をチェックする静的メソッドです。
5. 継承:extends
JavaScriptのクラスは、extends
キーワードを使用した単一継承をサポートしています。
式のclass Child extends Parent { }
Child
クラスはParent
コンストラクタ、フィールド、およびメソッドを継承します。
たとえば、親クラスContentWriter
を拡張する新しい子クラスUser
を作成しましょう。,
ContentWriter
User
コンストラクタ、メソッド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
と評価されます。
同時にContentWriter
はUser
の子クラスです。 したがって、writer instanceof User
はtrue
同様に評価されます。
インスタンスの正確なクラスを決定したい場合はどうすればよいですか?, 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のクラスはますます便利になります。
#
を使用してプライベートプロパティの接頭辞を付けることについてどう思いますか?