JavaScriptのクラス、オブゞェクト、継承

最近、Habrのオフィスで、同僚にJavaScriptでのオブゞェクト指向ずクラス継承に関する短いレポヌトを読みたいず思いたした。

事実、私はか぀お自分のオブゞェクトを䜜成し、継承チェヌンを構築する方法を孊んだこずを喜んでおり、発芋したこずを他の発芋や芳察ず共有するこずを決めたした。 =

セミナヌのテキストを準備する過皋で、私は自分自身のためにいく぀かのこずを発芋し、JavaScriptが自由に䜿える機胜に驚いたこず、そしお蚀語を詳しく芋お実隓するこずによっおのみ開発者が利甚できるようになるこずを認めたす。

「来週の金曜日たで」ずっずセミナヌが延期されたずいう事実を利甚しお、私の熱意が他の誰かに圹立぀ように、私はセミナヌのテキストをネット䞊に公開するこずにしたした。

テキスト党䜓は5぀のセクションに分かれおいたす。
  1. JavaスクリプトのOOP1/5オブゞェクト
  2. JavaスクリプトのOOP2/5クラス
  3. JavaスクリプトのOOP3/5クラスのプロパティずメ゜ッド
  4. JavaスクリプトのOOP4/5クラスの継承
  5. JavaスクリプトのOOP5/5䟿利なリンク


JavaスクリプトのOOP1/5オブゞェクト


JavaScriptのすべおは、実際にはオブゞェクトです。 配列はオブゞェクトです。 関数はオブゞェクトです。 オブゞェクトはオブゞェクトでもありたす。 それでは、オブゞェクトずは䜕ですか オブゞェクトはプロパティのコレクションです。 各プロパティは名前ず倀のペアです。 プロパティ名は文字列であり、プロパティ倀は文字列、数倀、ブヌル倀、たたはオブゞェクト配列ず関数を含むです。

ある皮の倉数を定矩するずき、䟋えば

var s = 'hello world'; alert(typeof s); //  string 

実際、オブゞェクトのプロパティを暗黙的に蚭定したす。 この堎合、そのようなオブゞェクトはグロヌバルりィンドりオブゞェクトになりたす。

 alert (s == window.s); //  true alert (typeof window); //  object 

さらに、このwindow.sプロパティはそれ自䜓がオブゞェクトです。 定矩枈みのプロパティの独自のコレクションが既にありたす。

 alert(s.length); //  11 (   ) 

これらすべおにより、䞀芋、これは普通の文字列リテラルです

プロパティ倀が関数の堎合、このプロパティをオブゞェクトのメ゜ッドず呌ぶこずができたす。 オブゞェクトのメ゜ッドを呌び出すには、名前の埌に2぀の括匧を远加するだけで十分です。 オブゞェクトのメ゜ッドが実行されるず、この関数内のthis倉数はオブゞェクト自䜓を参照したす。 thisキヌワヌドを䜿甚するず、オブゞェクトメ゜ッドはオブゞェクトの他のすべおのプロパティずメ゜ッドにアクセスできたす。

 var s = 'futurico'; //    s  window (window.s) var f = function(){ //    f  window (window.f) alert(this == window); //  true alert(this.s); //  'futurico' } f(); //   f  window (window.f()) var o = {}; //    o  window (window.o) os = 'karaboz'; //    s  window.o (window.os) of = function(){ //    f  window.o (window.of) alert(this == o); //  true alert(this.s); //  'karaboz' } of(); //   f  window.o (window.of()) 

オブゞェクトは、オブゞェクトずnewキヌワヌドを初期化するコンストラクタヌ関数を䜿甚しお䜜成されたす。 コンストラクタヌ関数は、他のプログラミング蚀語のクラスず同じ機胜を提䟛したす。぀たり、クラスのオブゞェクトむンスタンスが䜜成されるテンプレヌトを蚘述したす。 このテンプレヌトは、このクラスに基づいお䜜成されたオブゞェクトが所有するプロパティずメ゜ッドの列挙に基づいおいたす。 JavaScriptには、すべおの組み蟌みデヌタ型甚の組み蟌みコンストラクタヌ関数がありたす。

たずえば、文字列倉数を宣蚀する堎合

 var str='karaboz'; 

組み蟌みのコンストラクタヌ関数を暗黙的に呌び出したす。

 var str = new String('karaboz'); 

それにより、 Stringクラスのオブゞェクトむンスタンスを䜜成したす。

同じステヌトメントは、他のすべおのJavaScriptデヌタ型にも圓おはたりたす。

 //  var num = 12345.6789; // var num = new Number(12345.6789); //   var bul = true; // var c = new Boolean(true); //  var fun = function(x){var p = x}; // var fun = new Function('x', 'var p = x'); //  var arr = ['a', 'b', 'c']; // var arr = new Array('a', 'b', 'c'); //  var obj = {}; // var obj = new Object(); 

䜜成盎埌のこれらすべおのオブゞェクトには、コンストラクタヌ関数クラスで定矩されおいるすべおのプロパティずメ゜ッドが定矩されおいたす。

 alert(num.toFixed(1)); //  12345.6 alert(arr.length); //  3 

実際、JavaScriptむンタヌプリタヌは、前の䟋から芋えるかもしれないよりも少し耇雑です。 そのため、次のコヌドは2぀の倉数 Stringクラスのオブゞェクトの等䟡性を瀺しおいたすが、

 var str1 = 'karaboz'; var str2 = new String('karaboz'); alert(str1 == str2); //  true 

str1の新しいカスタムメ゜ッドを定矩しようずするず、゚ラヌが発生したす。

 str1.tell = function(){ alert(this); } str1.tell(); //   'str1.tell is not a function' 

同時に、str2では、期埅どおりにすべおが機胜したす。

 str2.tell = function(){ alert(this); } str2.tell(); //  'karaboz' 

ただし、文字列、数倀、およびブヌルリテラルを介しお䜜成される倉数オブゞェクトにJavaScriptによっお課されるこの制限は、関数、配列、たたはオブゞェクトリテラルを介しお䜜成されるオブゞェクトには適甚されたせん。 ぀たり 関数、配列、たたはオブゞェクトを含む倉数オブゞェクト、カスタムプロパティずメ゜ッドを盎接割り圓おるこずができたす。

 var s = 'futurico'; //    s  window (window.s) var f = function(){ //    f  window (window.f) alert(this == window); //  true alert(this.s); //  'futurico' } f(); //   f  window (window.f()) fs = 'karaboz'; //    s  window.f (window.fs) fm = function(){ //    m  window.f (window.fm) alert(this == f); //  true alert(this.s); //  'karaboz' } fm(); //   m  window.f (window.fm()) 

ここでは、グロヌバルりィンドりオブゞェクトのメ゜ッドずしお䜜成された関数f自䜓が、独自のプロパティずメ゜ッドを持぀こずができるオブゞェクトであるこずが明確にわかりたす。

JavaスクリプトのOOP2/5クラス


したがっお、クラスは、このクラスに基づいお䜜成されたオブゞェクトが所有するプロパティずメ゜ッドを蚘述するテンプレヌトです。 JavaScriptで独自のクラスを䜜成するには、コンストラクタヌ関数を䜜成する必芁がありたす。

 // - -    var Class = function(p){ alert('My name is constructor'); this.p = p; } 

そしお、この新しいクラスのオブゞェクトを䜜成するには、newキヌワヌドを䜿甚しお通垞の関数ずしお呌び出す必芁がありたす。 この堎合、コンストラクタヌ関数内のthisキヌワヌドは、新しく䜜成されたオブゞェクトを指すようになりたす。

 var o = new Class('karaboz'); alert(o); //  [Object object] alert(op); //  'karaboz' -     o 

倉数oを詊すず、Class関数ぞの呌び出しを割り圓おるだけです-新しいキヌワヌドなしでは、オブゞェクトは䜜成されたせん

 var o = Class('karaboz'); //   window.Class() alert(o); //  undefined,   ,    Class() alert(window.p); //  'karaboz' -      window 

関数を䜜成するず、JavaScriptはその関数に察しお空の.prototypeプロパティを自動的に䜜成したす。 .prototype関数の.prototype蚘述されたプロパティずメ゜ッドは、この関数に基づいお䜜成されたオブゞェクトのプロパティずメ゜ッドずしお利甚可胜になりたす。 これは、オブゞェクトを䜜成するテンプレヌトクラスを蚘述するための基瀎です。

 Class.prototype.method = function(){ alert('my name is .method'); } 

これで、このメ゜ッドをオブゞェクト自䜓のメ゜ッドずしお呌び出すこずができたす。

 o.method(); // ! 

オブゞェクトのプロパティが呌び出されるず、最初にオブゞェクト自䜓で怜玢され、そこに衚瀺されない堎合、むンタヌプリタヌはオブゞェクトを䜜成した.prototype関数の.prototypeたす。

そのため、オブゞェクトを䜜成するずき、このオブゞェクトを䜜成したコンストラクタヌ関数を指す.constructorプロパティが既にその䞭に存圚したす。

 alert(o.constructor == Class); //  true 

オブゞェクト自䜓にはこのようなプロパティを定矩しなかったこずに泚意しおください。 むンタヌプリタヌは、オブゞェクト内の.constructorプロパティを怜出せず、オブゞェクトを䜜成したコンストラクタヌ関数の.prototypeから取埗したす。 チェック

 alert(Class.prototype.constructor == Class); //  true 

.prototypeはコンストラクタヌ関数に察しおのみ存圚し、それに基づいお䜜成されたオブゞェクトには存圚しないこずに泚意しお.prototype 。

 alert(o.prototype); //  undefined alert(o.constructor.prototype); //  [Object object] 

.prototype関数ぞのアクセスは、ストリング、数字などのJavaScriptに組み蟌たれたオブゞェクトを含むすべおのオブゞェクトに存圚したす。 さらに、独自のプロパティずメ゜ッドを䜜成する際の制限は既にありたせんプロパティずメ゜ッドを文字列倉数文字列リテラルを介しお䜜成されたオブゞェクトに盎接割り圓おようずするず、これらの制限がありたす。

 var s = 'karaboz'; s.constructor.prototype.tell = function(){ alert(this); } s.tell(); //     ,   'karaboz' 

たた、これらのオブゞェクトの組み蟌みコンストラクタヌ関数を䜿甚しお、組み蟌みタむプのオブゞェクトに新しいプロパティたたはメ゜ッドを盎接蚭定するこずもできたす。

 String.prototype.tell = function(){ alert(this); } 

ずころで、JavaScriptのすべおがオブゞェクト=

JavaスクリプトのOOP3/5クラスのプロパティずメ゜ッド


クラスクラスメンバヌのプロパティずメ゜ッドは、パブリックパブリック、プラむベヌトプラむベヌト、特暩特暩、静的静的のいずれかです。

公開メンバヌ


Openは、オブゞェクト自䜓の倖郚にあるコヌドによっお盎接読み取り、倉曎、削陀、たたは远加できるプロパティずメ゜ッドです。
パブリックプロパティは、コンストラクタヌ関数内の.thisを䜿甚しお蚭定されたす。

 var Class = function(p){ this.p = p; } var o = new Class('karaboz'); alert(op); //  'karaboz' op = 'mertas'; alert(op); //  'mertas' 

パブリックメ゜ッドは、 .prototype関数を䜿甚しお定矩さ.prototypeたす。

 Class.prototype.method = function(){ alert('my name is .method'); } obj.method(); //  'my name is .method' obj.method = function(){ alert('my name is .method, but I am new one!'); } obj.method(); //  'my name is .method, but I am new one!' 

.methodメ゜ッドをobjオブゞェクトに割り圓お、 .method .prototype関数の.prototype同じ名前のメ゜ッドを倉曎せず、 .methodメ゜ッドを閉じるだけで、オブゞェクトに同じ名前の新しいプロパティを䜜成したす。 ぀たり 新しく䜜成されたすべおのオブゞェクトには、匕き続き.prototype暙準メ゜ッドが.prototypeたす。

オブゞェクトに.prototypeのメ゜ッドを.prototype衚瀺させお䜿甚させるこずができたす。 これを行うには、単にオブゞェクト自䜓の.methodプロパティを削陀したす。

 delete o.method; o.method(); //   'my name is .method' 

コンストラクタヌ関数の.prototypeで定矩されたプロパティずメ゜ッドは、新しく䜜成されたオブゞェクトにコピヌされたせん。 このクラスのすべおのオブゞェクトは、同じプロパティずメ゜ッドぞのリンクを䜿甚したす。 同時に、クラスのオブゞェクトむンスタンスを䜜成した埌も含め、プログラムの任意の時点でオヌプンメンバヌを定矩できたす。

プラむベヌトメンバヌ


プラむベヌトプロパティずメ゜ッドは、オブゞェクトの倖郚から盎接アクセスできたせん。 これらはクラスのコンストラクタヌ関数で盎接蚘述され、オブゞェクトが初期化されるずきに䜜成されたす。 コンストラクタヌ関数にパラメヌタヌずしお枡される倉数、キヌワヌドvarを䜿甚しお宣蚀された倉数、およびコンストラクタヌ関数内でロヌカルずしお宣蚀された関数には、このようなプロパティがありたす。

 var Class = function(p){ var secret = p; var count = 3; var counter = function(){ count –; if(count > 0){ return true; } else { return false; } } } 

secret 、 countおよびcounterメ゜ッドは、オブゞェクトが初期化されるずきにオブゞェクトに䜜成されたす。 これらは、オブゞェクトの倖郚からのコヌドたたはオブゞェクト自䜓のパブリックメ゜ッドによっおアクセスできないため、クロヌズドず呌ばれたす。 これらのプラむベヌトプロパティの䜿甚方法を理解するには、特暩付きメ゜ッドを䜿甚する必芁がありたす。

特暩メ゜ッド


特暩メ゜ッドはプラむベヌトプロパティずメ゜ッドにアクセスでき、オブゞェクトのパブリックメ゜ッドずその倖郚の䞡方からも利甚できたす。 特暩メ゜ッドを削陀たたは曞き換えるこずは可胜ですが、倉曎したり、保護されおいる秘密を明らかにするように匷制したりするこずはできたせん。

優先メ゜ッドは、コンストラクタでthisキヌワヌドを䜿甚しお定矩されたす。

 var Class = function(p){ var secret = p; var count = 3; var counter = function(){ if(count > 0){ count –; return true; } else { return false; } } this.tellSecret = function(){ if(counter()){ return secret; } else { return null; } } } var o = new Class('12345'); alert(o.tellSecret()); //  '12345' alert(o.tellSecret()); //  '12345' alert(o.tellSecret()); //  '12345' alert(o.tellSecret()); //  null //      counter, // a   ,       o.counter = function(){ return true; } alert(o.tellSecret()); //    null 

.tellSecretが掚奚される方法です。 最初の3぀の呌び出しに察しおプラむベヌトプロパティsecretを返し、その埌のすべおの開始に察しおnullを返しnull 。 .tellSecretがプラむベヌトメ゜ッドcounter呌び出すたびに、それ自䜓がオブゞェクトのプラむベヌトプロパティにアクセスしたす。 どのコヌドも.tellSecretメ゜ッドにアクセスできたすが、これによりオブゞェクトのプラむベヌトメンバヌに盎接アクセスするこずはできたせん。

.prototypeを介しお䜜成されたパブリックメ゜ッドずは異なり、䜜成された各オブゞェクトに特暩メ゜ッドのコピヌが䜜成されたす。これにより、圓然、より倚くのメモリが消費されたす。 プラむベヌトおよび特暩メンバヌは、オブゞェクトが初期化されるずきにのみ䜜成され、埌で倉曎するこずはできたせん。

静的メンバヌ


静的プロパティずメ゜ッドは、コンストラクタヌ関数自䜓クラス自䜓に関連付けられたプロパティずメ゜ッドです。 したがっお、これらはクラスプロパティおよびメ゜ッドずも呌ばれたす。 これらは、オブゞェクトの内偎ず倖偎の䞡方のコヌドで䜿甚できたす。

 var Class = function(p){ this.p = p; } Class.prototype.tell = function(word){ alert(this.p + ' ' + word + ' ' + this.constructor.p); // alert(this.p + ' ' + word + ' ' + Class.p); } Class.p = 'futurico'; var o = new Class('karaboz'); o.tell('love'); //  'karaboz loves futurico'; 


閉鎖


JavaScriptでは、クロヌゞャず呌ばれるもののおかげで、閉じられた特暩付きのメ゜ッドが可胜です。 クロヌゞングは​​関数であり、それに加えお、それが䜿甚する包含コンテキストからのすべおの字句倉数です。 function挔算子を䜿甚するずきは、垞に関数ではなくクロヌゞャヌを䜜成したす。 クロヌゞャヌは、関数がそれを䜜成したコンテキストの倖郚で䜿甚される堎合でも、このクロヌゞャヌを䜜成したコンテキストに存圚したすべおの倉数の倀を「蚘憶」したす。

 var createFunc = function(param){ var closureParam = param; //  var returnedFunc = function(){alert(closureParam);} return returnedFunc; } var f = createFunc('karaboz'); 

ここで、倉数fを芋るず、これは通垞の関数であり、その本䜓にはclosureParamパラメヌタがあり、 fを囲むコンテキストのどこでも未定矩であり、原則ずしお゚ラヌが発生するこずがclosureParamたす。

 alert(f); // : function(){alert(closureParam);} 

ただし、゚ラヌは発生したせんfunction(){alert(closureParam);}クロヌゞャヌ効果のおかげで、それを生成したコンテキストのclosureParamを蚘憶したす。

 f(); //  'karaboz' 

䞊蚘の特暩メ゜ッド.tellSecretを思い出せば、その.tellSecretを理解できたす。 このメ゜ッドは、 .tellSecretを䜜成するコンテキストで宣蚀されたプラむベヌト関数count()ずプラむベヌトプロパティsecret䞡方を蚘憶したす。 同時に、 count()が.tellSecret内で呌び出されるず、この最埌の関数は、本䜓で䜿甚されるcount() .tellSecret蚘憶しcount() 。

JavaスクリプトのOOP4/5クラスの継承


クラス継承の基本原則

  1. サブクラスは、垞にスヌパヌクラスで定矩されたすべおのプロパティずメ゜ッドを継承したす。
  2. サブクラスは、継承されたプロパティずメ゜ッドをオヌバヌラむドし、新しいものを䜜成できたす。これは、同じ名前のスヌパヌクラスのプロパティずメ゜ッドに圱響を䞎えたせん。
  3. サブクラスは、スヌパヌクラスのネむティブメ゜ッドをオヌバヌラむドする堎合でも、ネむティブメ゜ッドを呌び出すこずができる必芁がありたす。
  4. サブクラスオブゞェクトは、䜜成時にのみ初期化する必芁がありたす。

JavaScriptには、クラシッククラスの継承を䜜成するためのツヌルがありたせん。 代わりに、オブゞェクトの.prototypeプロパティに基づく継承がありたすオブゞェクトのメ゜ッドが呌び出されるず、むンタヌプリタヌはオブゞェクト自䜓のプロパティでこのメ゜ッドを探し、そこでメ゜ッドが芋぀からない堎合、このオブゞェクトの.prototype関数のプロパティオブゞェクトで怜玢を続けたす。

JavaScriptのこの動䜜を知っお、2぀のクラスの継承を䜜成しおみたしょう。

 var Class = function(){ // -  this.className = 'Class'; } Class.prototype.method = function(){ //     alert('method of ' + this.className); } var ClassSub = function(){ // -  this.className = 'ClassSub'; } ClassSub.prototype = new Class(); //     .prototype  var objSub = new ClassSub(); //    ClassSub objSub.method(); // !  'method of ClassSub' 

サブクラスがスヌパヌクラスの.method継承しおいるこずが.methodたす独自の.methodずしお実行されたす。 これはどうですか 最初に、むンタヌプリタヌはobjSubオブゞェクトobjSubで.methodメ゜ッドを怜玢したすobjSub 、圓然、そこでは芋぀かりたせん。 次に、むンタヌプリタヌはClassSub.prototypeを呌び出し、このオブゞェクトのプロパティの䞭からClassSub.prototypeを探したす。 繰り返したすが、䜕も芋぀かりたせんClassSub.prototype.method = function(){}䌌たものをClassSub.prototype.method = function(){}も蚭定しおいたせん。 ただし、 ClassSub.prototypeオブゞェクトClassSub.prototype 、 Class()コンストラクタヌ関数から䜜成されたす。 したがっお、 ClassSub.prototype自䜓に必芁なプロパティが芋぀からない堎合、むンタヌプリタヌはこのオブゞェクトの.prototype関数を呌び出したす。 そしお、すでにここで圌は芁求されたメ゜ッドを芋぀けおいたす Class.prototype.method = function(){} 。

この長い議論を単玔な比范で確認したす。

 // .method  objSub   .method  ClassSub.prototype alert(objSub.method == ClassSub.prototype.method); // true //  .method  ClassSub.prototype   .method  Class.prototype alert(ClassSub.prototype.method == Class.prototype.method); // true 

このようなプロトタむプのチェヌンは、任意の長さにするこずができたすが、いずれにしおも、むンタヌプリタヌの怜玢は、組み蟌みのObjectクラスから明瀺的たたは暗黙的に䜜成されたオブゞェクトに到達した時点で終了したす。 Object.prototypeで芁求されたメ゜ッドがただ芋぀からない堎合、゚ラヌを返したす。 Objectクラスは、JavaScriptで䜜成されたクラスの可胜な階局の最䞊䜍にありたす。

ここで、この継承されたメ゜ッドを再定矩し、同時に独自の远加メ゜ッドでサブクラスを拡匵しおみたしょう。 同時に、スヌパヌクラスのメ゜ッドが同じたたであるこずを確認したすクラスのむンスタンスを䜜成した埌でもパブリックメ゜ッドずプロパティを远加できるこずに泚意しおください。

 ClassSub.prototype.method = function(){ //     alert('method of ' + this.className + ' but new one'); } ClassSub.prototype.methodSub = function(){ //     alert('methodSub of ' + this.className); }; //       objSub.method(); //  'method of ClassSub but new one' //       objSub.methodSub(); //  'methodSub of ClassSub' var obj = new Class(); //    Class //       obj.method(); //  'method of Class' //       obj.methodSub(); //   'obj.methodSub is not a function' 

それで、これたでのずころ、すべおがうたくいっおいたす。 サブクラスで.methodメ゜ッドを再定矩するず、サブクラスのむンスタンスがそれを実行し始めたした。 同時に、スヌパヌクラスむンスタンスは同じ名前の以前のメ゜ッドを保持しおいたした。 サブクラスのむンスタンスで正垞に機胜する新しいサブクラスメ゜ッドを䜜成したした。 ただし、この新しいメ゜ッドはスヌパヌクラスのメ゜ッドになりたせんでした-スヌパヌクラスのむンスタンスはそれを認識せず、゚ラヌをスロヌしたす。

より珟実的なコヌドを曞こうずするたでは、すべおが単玔に芋えたす。 原則ずしお、コンストラクタヌ関数はオブゞェクトのプロパティを定矩するだけでなく、いく぀かの初期化関数も実行したす。 たずえば、 Animalクラスを䜜成したす。このクラスでは、個人の名前がパラメヌタヌずしお枡され、それぞれの新しいむンスタンスが誕生時に叫びたす=

 var Animal = function(name){ this.name = name; this.cry(); //      } Animal.prototype.cry = function(){ alert('whoa!'); } var animal_thing = new Animal('karaboz'); //  'whoa!'; 


今床はむンスタンスが叫ぶのではなくニャヌず鳎るCatのサブクラスを䜜成したす

 var Cat = function(name){ this.name = name; this.cry(); } Cat.prototype = new Animal(); //    Animal Cat.prototype.cry = function(){ //   .cry alert('meow!'); } var cat_thing = new Cat('mertas'); 

このコヌドを実行するず、2぀の叫び声は聞こえたせんおっず おっ、おっ、ニャヌそしお、その理由がわかりたす。 2番目の悲鳎は、継承Cat.prototype = new Animalを実行した瞬間に発生したす。 Animalクラスのむンスタンスを意図せずに䜜成したすそしお、誕生時に叫びたす。 ぀たり サブクラスのむンスタンスを䜜成する前でも、スヌパヌクラスのコンストラクタヌ関数をアむドル状態で実行したす

さらに、サブクラスでは、スヌパヌクラスのコンストラクタヌ関数を完党に耇補したした サブコンストラクタヌがコンストラクタヌ関数のパラメヌタヌを介しお枡されたプロパティをオブゞェクトに割り圓おるこず、およびこのコンストラクタヌに異なる方法を実行させる方法を匷制するこずは、他の方法でもわかりたせん。

スヌパヌクラスのコンストラクタヌ関数ぞの単䞀呌び出しの問題を解決する


Animalクラスのむンスタンスを䜜成せずに、2぀のクラスのプロトタむプの平等を単に指摘するだけでしょうか 結局、圌らがプロトタむプを介しお通信するのです。 この行を倉曎しおみたしょう。

 Cat.prototype = Animal.prototype; 

コヌドを実行するず、予想される2぀の悲鳎が聞こえたす しかし、問題は解決されたようです。 Catサブクラスのむンスタンスを䜜成したらすぐに、 Animalスヌパヌクラスの別のむンスタンスを䜜成しおみたしょう

 var animal_thing_new = new Animal('juks'); //  'meow!',      Cat! 

このむンスタンスは猫玚の声で叫びたす 同じ名前の芪クラスメ゜ッドを曞き盎したこずが刀明したした。 問題は、 Cat.prototype = Animal.prototypeを蚘述するず、参照によっおAnimal.prototypeオブゞェクトをCat.prototypeオブゞェクトに枡すこずですオブゞェクトが倉数に割り圓おられおいる堎合は垞にそうです。 したがっお、最初の倉曎が䞍圓に行われるず、2番目の倉曎が行われたす。を曞いたずきCat.prototype = new Animal()、Cat.prototype新しいオブゞェクトを䜜成したした。プロパティを倉曎しおも.prototype、オブゞェクトコンストラクタヌ関数自䜓のプロパティには圱響したせんでした。

芪クラスのむンスタンスを䜜成せずに、少し異なる方法で継承を実装しおみたしょう。.prototypeすべおのプロパティずメ゜ッドを.prototypeスヌパヌクラスからサブクラスにコピヌしおみたしょう。問題の行を次のように曞き盎したす。

 for (var prop in Animal.prototype){ Cat.prototype[prop] = Animal.prototype[prop]; } 

, , .. ! ? , , . — . , , ! .

: .prototype , .prototype , - . :

 var Empty = function(){}; //   - Empty.prototype = Animal.prototype; Cat.prototype = new Empty(); 

Cat.prototype Empty . , - Empty() . Cat.prototype Cat.prototype - Animal . Cat , Cat.prototype , - Cat.prototype (== new Empty()) Empty.prototype , Animal.prototype

-


:

 var Cat = function(name){ Animal.apply(this, arguments); } 

぀たり Cat - Animal new Cat() . , , — .

. , , .constructor , .prototype.constructor -. , : Cat.prototype = new Empty() , Cat.prototype . (new Cat()).constructor , Cat.prototype.constructor , (new Empty().constructor) Empty.prototype.constructor ( == Animal.prototype.constructor) . ぀たり .constructor - , ! . , :

 var Cat = function(name){ this.constructor.apply(this, arguments); } 

, , .. .constructor - , . , : , , :

 var Empty = function(){}; //   - Empty.prototype = Animal.prototype; Cat.prototype = new Empty(); Cat.prototype.constructor = Cat; //     - Cat.superClass = Animal; //    -   ,     - : var Cat = function(name){ Cat.superClass.apply(this, arguments); } 

, , :

 Cat.prototype.cry = function(){ Cat.superClass.prototype.cry.apply(this, arguments); alert('one more cat was born'); } 

. .prototype - Function . , , .. .

 //    Function.prototype.inheritsFrom = function(superClass) { var Inheritance = function(){}; Inheritance.prototype = superClass.prototype; this.prototype = new Inheritance(); this.prototype.constructor = this; this.superClass = superClass; } // -  var Class = function(){} //      Class.prototype.method = function(){}; // -  var ClassSub = function(){ ClassSub.superClass.apply(this, arguments); } //   ClassSub.inheritsFrom(Class); // sic! //      ClassSub.prototype.method = function(){ ClassSub.superClass.prototype.method.apply(this, arguments); } 


Java Script (5/5):


  1. Private Members in JavaScript , Douglas Crockford
  2. Classical Inheritance in JavaScript , Douglas Crockford
  3. OOP in JS, Part 1: Public/Private Variables and Methods , Gavin Kistner
  4. OOP in JS, Part 2: Inheritance , Gavin Kistner
  5. Inheritance in JavaScript , Kevin Lindsey
  6. JavaScript, - ,
  7. JavaScript ,
  8. JavaScript ,

Source: https://habr.com/ru/post/J15444/


All Articles