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 ,



All Articles