実際に両方の方法を比較して、どちらが速いか見てみましょう: http://jsperf.com/traditional-oop-vs-derek-s-oop-variant
ご覧のとおり、この方法は従来の方法よりもはるかに遅いです。理由は次のとおりです。
- コンストラクターが必要以上の処理を行っています。したがって、複数のインスタンスを作成すると、インスタンスを作成するための追加コストが加算されます。
- @Alxandrが述べたよう
method
に、正当な理由もなく新しいインスタンスを作成するたびに、新しい匿名関数を作成しています。一度しか役に立たず、その後は処理能力を浪費します。
prototype
コンストラクターの に特定のメソッドがあるかどうかを確認し、ない場合はメソッドを に追加する関数を呼び出してprototype
います。これは不必要に思えます。これを行うための関数を作成する必要はありません。私見関数呼び出しは単なる追加のオーバーヘッドです。
あなたが批判を求めたので:
Object.prototype
拡張が良い習慣とは見なされていないことは承知しています。しかし、それ以外に、このアプローチの欠点はありますか?
あなたのアプローチは非常に遅いだけでなく、次のような問題もあります。
- わかりにくい。このアプローチは直感的にわかるかもしれません。しかし、あなたのコードを読んだ人は、関数が何をするのか疑問に思うでしょう
this.method
。Object.prototype.method
コードを完全に理解するには、 の定義を読む必要があります。
- 直感的ではない。
prototype
前に述べたように、コンストラクター内でプロパティを定義しても意味がありません。一度だけ必要で、その後は追加手荷物になります。prototype
コンストラクター ロジックとプロパティを分離しておくことをお勧めします。
- 予期しない動作につながる可能性があります。@basilikumが指摘したように、コンストラクターを呼び出さないと、
prototype
プロパティは設定されません。これにより、 のプロパティにアクセスしようとすると問題が発生する可能性がありprototype
ます。たとえば、prototype
プロパティを継承しない場合、基本コンストラクターが呼び出されるまで継承されません。
あなたの目標は、コンストラクターとprototype
プロパティの両方を単一のエンティティにカプセル化することだと思います。
ただし、関数定義をコンストラクターで分離せずに、プロトタイプで関数を定義する方法を考え出そうとしていました。
これを行う簡単な方法はありますか?見てみましょう、JavaScript はプロトタイプのオブジェクト指向言語です。prototype
したがって、コンストラクターではなくにもっと焦点を当てる必要があります。
上の図は、次の回答から取得したものです: https://stackoverflow.com/a/8096017/783743
この図は次のことを示しています。
prototype
すべてのコンストラクターには、コンストラクター関数のプロトタイプ オブジェクトを指すというプロパティがあります。
- すべてのプロトタイプには
constructor
、プロトタイプ オブジェクトのコンストラクター関数を指す と呼ばれるプロパティがあります。
- コンストラクター関数からインスタンスを作成します。ただし、インスタンスは実際に
prototype
はコンストラクターではなく から継承します。
これは非常に有益な情報です。従来、コンストラクター関数を最初に作成してから、そのprototype
プロパティを設定していました。constructor
ただし、この情報は、最初にプロトタイプ オブジェクトを作成してから、代わりにそのプロパティを定義できることを示しています。
たとえば、伝統的に次のように書くことができます。
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
ただし、新たに発見した知識を使用すると、次のように同じことを書くことができます。
var shape = {
constructor: function () {
this.x = 0;
this.y = 0;
},
move: function (x, y) {
this.x += x;
this.y += y;
}
};
これらの両方の例に含まれる情報は同じです。ただし、2 番目の例を機能させるには、少し足場を追加する必要があります。特に、次のことを行う必要があります。
var Shape = shape.constructor;
Shape.prototype = shape;
これは大きな問題ではありません。これを行う関数を作成するだけです。
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
Shape
これで、次のように定義できます。
var Shape = defclass({
constructor: function () {
this.x = 0;
this.y = 0;
},
move: function (x, y) {
this.x += x;
this.y += y;
}
});
ご覧のとおり、カプセル化は JavaScript で簡単に実現できます。あなたがする必要があるのは、横向きに考えるだけです。ただし、継承は別の問題です。継承を実現するには、もう少し作業を行う必要があります。
これが役に立ったことを願っています。