パターンでは、オブジェクトはコンストラクターで作成され、そのメソッドはプロトタイプで宣言されます。
このパターンは、Google Closure Libraryなどのフレームワークで使用されます。 ネイティブJavaScriptオブジェクトもこのパターンを使用します。
擬似クラス宣言
JavaScriptにはC、Java、PHPなどのような他の言語のようなクラスがないため、擬似クラスという用語が選択されましたが、このパターンはクラス定義に近いものです。
擬似クラスは、コンストラクター関数とメソッドで構成されます。
たとえば、
Animal
擬似クラスは、1つの
sit
メソッドと2つのプロパティで構成されます。
function Animal(name) { this.name = name } Animal.prototype = { canWalk: true, sit: function() { this.canWalk = false alert(this.name + ' sits down.') } } var animal = new Animal('Pet')
new Animal(name)
が呼び出されると、オブジェクトはAnimal.prototype
へのAnimal.prototype
リンクをAnimal.prototype
(図の右側を参照)。animal.sit
メソッドは、インスタンス内のanimal.canWalk
を変更するので、他の人ができるのに対して、私たちの動物はもはや歩くことができません。

擬似クラススキーマ:
- デフォルトのメソッドとプロパティはプロトタイプで定義されています。
prototype
メソッドはthis
使用します。thisの値は呼び出しのコンテキストに依存するため、現在のオブジェクトを指します。 したがって、 animal.sit()
では、 this
はanimal
指します。
継承
Animal
から継承する新しいクラス、たとえば
Rabbit
作成しましょう。
function Rabbit(name) { this.name = name } Rabbit.prototype.jump = function() { this.canWalk = true alert(this.name + ' jumps!') } var rabbit = new Rabbit('John')
ご覧のとおり、ウサギは
Animal
と同じ構造をしています-メソッドはプロトタイプで定義されています。
Animal
から継承するには、
Rabbit.prototype.__proto__ == Animal.prototype
を継承する必要があります。 メソッドが
Rabbit.prototype
で見つからない場合、親
Animal.prototype
メソッドで検索するため、これは自然な要件
Animal.prototype
。
このように、例えば:

これを実装するには、まず
Rabbit.prototype
から継承した空の
Rabbit.prototype
オブジェクトを作成してから、メソッドを追加する必要があります。
function Rabbit(name) { this.name = name } Rabbit.prototype = inherit(Animal.prototype) Rabbit.prototype.jump = function() { ... }
inherit
は、指定された
__proto__
空のオブジェクトを作成します。
function inherit(proto) { function F() {} F.prototype = proto return new F }
最後に起こったことは次のとおりです。
継承にnew Animal
を使用しないでください
Rabbit.prototype = inherit(Animal.prototype)
代わりに次のことを行うのは、よく知られていますが、正しい継承方法ではありません。
その結果、プロトタイプに
new Animal
が
new Animal
れます。
new Animal
Animal.prototype
自然に継承するため、継承は
Animal.prototype
ます。
...しかし、
new Animal()
は
name
なしで呼び出すことができると言ったのは誰ですか? コンストラクターは厳密に引数を必要とし、引数なしで死ぬことができます。
実際、問題はこれよりも概念的です。
Animal
は作成しません。 私たちは彼から継承したいだけです。
これが、
Rabbit.prototype = inherit(Animal.prototype)
が望ましい理由
Rabbit.prototype = inherit(Animal.prototype)
。 副作用のないきちんとした継承。
スーパークラスコンストラクターコール
スーパークラスコンストラクターが自動的に呼び出されるようになりました。 現在のオブジェクトに対して
Animal.apply()
を使用して、ハンドルで呼び出すことができます。
function Rabbit(name) { Animal.apply(this, arguments) }
このコードは、現在のオブジェクトのコンテキストで
Animal
コンストラクターを実行し
name
インスタンスの
name
設定
name
ます。
メソッドの再定義(多態性)
親メソッドをオーバーライドするには、子プロトタイプで置き換えます:
Rabbit.prototype.sit = function() { alert(this.name + ' sits in a rabbity way.') }
rabbit.sit()
が呼び出されると、
sit
はチェーン
rabbit -> Rabbit.prototype -> Animal.prototype
によって検索され、
Rabbit.prototype
に到達する前に
Animal.prototype
ます。
もちろん、オブジェクト内で直接、別の方法で再定義できます。
rabbit.sit = function() { alert('A special sit of this very rabbit ' + this.name) }
オーバーライド後に親メソッドを呼び出す
メソッドをオーバーライドした後でも、親メソッドを呼び出す必要がある場合があります。 これは、親プロトタイプを直接使用する場合に可能です。
Rabbit.prototype.sit = function() { alert('calling superclass sit:') Animal.prototype.sit.apply(this, arguments) }
すべての親メソッドは、現在のオブジェクトが
this
として渡される
apply/call
で呼び出され
apply/call
。
Animal.prototype.sit()
への単純な呼び出しは、
this
として
Animal.prototype
を使用し
this
。
砂糖:親への直接参照の削除
前の例では、親クラスを直接呼び出しました。 コンストラクターとして:
Animal.apply...
、またはメソッド:
Animal.prototype.sit.apply...
実際、これを行うべきではありません。 屈折処理中に、名前を変更したり、階層の中間クラスを追加したりできます。
通常、プログラミング言語では、
parent.method()
や
super()
などの特別なキーワードを使用して親メソッドを呼び出すことができます。
しかし、これはJavaScriptの場合ではありませんが、モデル化できます。
次の関数は継承を拡張し、直接参照せずに親とコンストラクタを設定します。
function extend(Child, Parent) { Child.prototype = inherit(Parent.prototype) Child.prototype.constructor = Child Child.parent = Parent.prototype }
だからここで使用できます:
function Rabbit(name) { Rabbit.parent.constructor.apply(this, arguments)
その結果、
Animal
名前を変更したり、中間の
GrassEatingAnimal
クラスを作成したりできます
GrassEatingAnimal
と
extend(...)
のみが影響を受けます。
プライベートで安全な方法(カプセル化)
保護されたメソッドとプロパティは、命名規則によってサポートされています。 アンダースコア「_」で始まるメソッドは、外部から呼び出すべきではありません(実際には可能です)。

プライベートメソッドはサポートされていません。
静的メソッドとプロパティ
静的メソッドとプロパティはコンストラクターで定義されます:
function Animal() { Animal.count++ } Animal.count = 0 new Animal() new Animal() alert(Animal.count)
合計
スーパーメガOOPフレームワークは次のとおりです。
function extend(Child, Parent) { Child.prototype = inherit(Parent.prototype) Child.prototype.constructor = Child Child.parent = Parent.prototype } function inherit(proto) { function F() {} F.prototype = proto return new F }
使用法:
たとえば、あるオブジェクトから別のオブジェクトにプロパティをコピーする関数など、少しだけ砂糖をフレームワークに追加できます。
mixin(Animal.prototype, { run: ..., toString: ...})
ただし、実際には、このOOPパターンを使用する必要はありません。 これを処理できるのは2つの関数のみです。