そのため、継承の問題(JSにはありません)についてはすでに多くのことが書かれています。 あまり重要ではないが、より重要な落とし穴であるメソッドの有能な実装についてお話します。
プログラマは、使い慣れた形式でクラスを宣言しようとします。これにより、メモリリークやその他の不快なことが発生します。 実際、プロトタイプを使用する方法を学ぶ必要があります。
この記事は、主に初心者のJSプログラマを対象としています。
以下では、パスカルまたはTse-two-crossesで理解されるという意味で「クラス」の概念を使用します。 一般的に言えば、JSにはそのようなクラスはありませんが、フォームと意味が非常に似ているものがあります。
当初から、次の2つの基本事項がすべての人に知られるようになりました。
- クラスはコンストラクター関数によって記述されます。
- メソッドは関数のプロパティです。
したがって、プログラマは非常に自然に書き始めます。
function Test(){ // this.x=5; this.y=3; // this.sum=function(){ return this.x+this.y; } // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); }
その後、2つのプロパティx(元は5)とy(元は3)を持つTestクラスと、xとyの合計を計算するsumメソッドを取得したようです。 構築すると、x、プレーヤー、および合計を含むeletが表示されます。
しかし、 実際に何が起こるのでしょうか? Testオブジェクトを作成する場合、Test関数が毎回呼び出されます。 そして、新しい匿名関数を作成し、それをsumプロパティに割り当てるたびに! その結果、各オブジェクトは独自のメソッドsumを作成します 。 100個のTestオブジェクトを作成すると、メモリ内の100個のsum関数が取得されます。
明らかに、これはできません。 そして、できるだけ早くこれを実現することが重要です。
この事実を理解した後、初心者プログラマーはしばしば次のことを行います。彼らはsum関数を個別に作成し、コンストラクターでそれをプロパティに割り当てます。
function Test(){ // this.x=5; this.y=3; // this.sum=Test_sum; // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // function Test_sum(){ return this.x+this.y; }
その結果、実際、Test_sum関数は一度だけ作成され、新しいTestオブジェクトが作成されるたびに、合計リンクのみが作成されます。
同時に、これは文盲のオプションです。 JavaScriptのコアであるプロトタイプを使用して、すべてをはるかに美しく正確に行うことができます。
function Test(){ // this.x=5; this.y=3; // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // Test.prototype.sum=function(){ return this.x+this.y; }
Testクラスのsumプロパティを作成するのではなく、そのプロトタイプを作成します。 したがって、各Testオブジェクトには合計関数があります。 実際、それが彼がすべてのオブジェクトが持っているものを記述するためのプロトタイプである理由です。 さらに、通常の機能しないプロパティをプロトタイプに組み込むことは論理的です。
function Test(){ // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // , , Test.prototype.x=5; Test.prototype.y=3; Test.prototype.sum=function(){ return this.x+this.y; }
悪い点は、プロパティとメソッドの宣言がコンストラクターで使用された後に行われることです。 しかし、あなたはそれに我慢しなければなりません...
Test.prototypeの複数の繰り返しもここでは不快です。 ある観点から、JSはTse-two-crossではなく、提案があることを思い出してください。 一方、 評判の良い人の多くは 、withの使用をまったく推奨していません。 したがって、 次のオプションは使用しないでください 。
文字通り、不快な驚きが私たちを待っています:このコードは機能しません。
function Test(){ // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // , , with(Test.prototype){ x=5; y=3; sum=function(){ return this.x+this.y; } }
なぜ機能しないのかは、なんらかの謎です。 好むと好まざるとにかかわらず、 プロトタイプという言葉を繰り返す必要があります。
function Test(){ // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); } // , , with(Test){ prototype.x=5; prototype.y=3; prototype.sum=function(){ return this.x+this.y; } }
ここでの利点は、Testクラスの全体の宣言を1つのブロックにグループ化することです(残りのコンストラクターを除く)。 ただし、少なくとも3つの構文を使用して関数を宣言できることを思い出せば、これに対処できます。
with(Test=function(){ // alert("Constructor: x="+this.x+", y="+this.y+", sum="+this.sum()); }){ // prototype.x=5; prototype.y=3; // prototype.sum=function(){ return this.x+this.y; } }
結果は、 これが プロトタイプ に置き換えられない限り、私たちが始めたほぼ自然な記録です。 さて、彼らは最初の「他の建設的な行動」に移動しました-残念ながら、私はこれに我慢しなければなりません。
ただし、プロパティとメソッドを作成する以外にコンストラクタから何も必要とされない場合、美しさが完全に得られます。
with(Test=new Function){ // prototype.x=5; prototype.y=3; // prototype.sum=function(){ return this.x+this.y; } }
ただし、with句は推奨されないことを忘れないでください。 したがって、最終的には、アナウンスの3番目のバージョンに焦点を当てます。