コンストラクタの借用この手法の基本的な考え方は単純です。サブタイプ コンストラクター内からスーパータイプ コンストラクターを呼び出します。また、関数は特定の環境でコードを実行するオブジェクトにすぎないため、apply() メソッドと call() メソッドを使用すると、新しく作成されたオブジェクトでコンストラクターを実行することもできます。 関数 Box(名前){ this.name = 名前 } ボックスプロトタイプ年齢 = 18 関数デスク(名前){ Box.call(this, name) // オブジェクトの偽装、オブジェクトの偽装はコンストラクタ内の情報のみを継承できます} var デスク = 新しいデスク('ccc') console.log(desk.name) // --> ccc console.log(desk.age) // --> 未定義 このことから、インスタンス プロパティのみが継承され、プロトタイプのプロパティにはアクセスできないことがわかります。このパターンは 2 つの問題を解決します。パラメータの受け渡しと継承は可能ですが、プロトタイプがないと再利用できません。 コンポジション継承関数 Box(名前){ this.name = 名前 } Box.prototype.run = 関数 (){ console.log(this.name + '実行中...') } 関数デスク(名前){ Box.call(this, name) // オブジェクトの偽装} Desk.prototype = new Box() // プロトタイプチェーン var desk = new Desk('ccc') console.log(desk.name) // --> ccc desk.run() // --> ccc が実行中です... この継承方法の背後にある考え方は、プロトタイプ チェーンを使用してプロトタイプ プロパティとメソッドを継承し、コンストラクターを使用してインスタンス プロパティを継承することです。 プロトタイプ継承プロトタイプの継承: プロトタイプを使用すると、カスタム タイプを作成しなくても、既存のオブジェクトに基づいて新しいオブジェクトを作成できます。これについて言えば、ある人物について言及しなければなりません。Douglas Crockford 氏は、2006 年に執筆した記事「Javascript でのプロトタイプ継承」で、次のようなメソッドを紹介しました。 function object(o) { // リテラル関数を渡す function F(){} // コンストラクターを作成する F.prototype = o; // リテラル関数をコンストラクターのプロトタイプに割り当てる return new F() // 最後にインスタンス化されたコンストラクターを返す } 次の例を考えてみましょう。 関数obj(o) { 関数F(){} F.プロトタイプ = o; 新しいF()を返す } var ボックス = { 名前: 'ccc', 年齢: 18歳 家族: ['兄弟','姉妹'] } var box1 = obj(ボックス) console.log(box1.name) // --> ccc box1.family.push('姉妹') console.log(box1.family) // --> ["兄弟", "姉妹", "姉妹"] var box2 = obj(ボックス) console.log(box2.family) // --> ["兄弟", "姉妹", "姉妹"] 上記コードの実装ロジックはプロトタイプチェーン継承と非常に似ているため、参照配列、つまりファミリ属性が共有されます。 寄生遺伝関数obj(o) { 関数F(){} F.プロトタイプ = o; 新しいF()を返す } 関数create(o){ var clone = obj(o) // 関数を呼び出して新しいオブジェクトを作成します clone.sayName = function(){ // 何らかの方法でこのオブジェクトを強化します console.log('hi') } return clone // このオブジェクトを返す } var 人 = { 名前: 'ccc', 友達: ['aa','bb'] } var anotherPerson = create(人) anotherPerson.sayName() // --> こんにちは この例のコードは、person に基づいて新しいオブジェクト anotherPerson を返します。新しいオブジェクトには person のすべてのプロパティとメソッドがあるだけでなく、独自の sayHi() メソッドもあります。寄生継承は、カスタム型やコンストラクターではなくオブジェクトを主に考慮する状況でも役立つパターンです。寄生継承を使用してオブジェクトに関数を追加すると、関数を再利用できないため効率が低下します。これはコンストラクター パターンに似ています。 寄生的組み合わせ継承前述したように、複合継承は JavaScript で最も一般的に使用される継承モードですが、独自の欠点もあります。複合継承の最大の問題は、状況に関係なく、スーパータイプ コンストラクターが 2 回呼び出されることです。1 回はサブタイプ プロトタイプを作成するときに、もう 1 回はサブタイプ コンストラクター内で呼び出されます。はい、サブタイプには最終的にスーパータイプ オブジェクトのすべてのインスタンス プロパティが含まれますが、サブタイプ コンストラクターを呼び出すときにこれらのプロパティを書き換える必要があります。次の例を見てみましょう。 関数SuperType(名前){ this.name = 名前; this.colors = ['赤','黒'] } SuperType.prototype.sayName = 関数 (){ console.log(この名前) } 関数 SubType(名前, 年齢){ SuperType.call(this, name) // SuperType への 2 回目の呼び出し this.age = 年齢 } SubType.prototype = new SuperType() // SuperTypeへの最初の呼び出し SubType.prototype.constructor = サブタイプ SubType.prototype.sayAge = 関数 (){ コンソールログ(this.age) } SuperType コンストラクターが初めて呼び出されると、SubType.prototype は name と colors という 2 つのプロパティを取得します。これらはすべて SuperType のインスタンス プロパティですが、現在は SubType のプロトタイプに配置されています。 SubType コンストラクターが呼び出されると、SuperType コンストラクターが再度呼び出され、新しいオブジェクトにインスタンス属性の名前と色が再度作成されます。したがって、これら 2 つのプロパティは、プロトタイプ内の同じ名前を持つ 2 つのプロパティをマスクします。つまり、名前と色の属性のセットが 2 つあります。1 つはインスタンスにあり、もう 1 つはプロトタイプにあります。これは、SuperType コンストラクターを 2 回呼び出した結果です。この問題の解決策は寄生的組み合わせ継承です。 関数オブジェクト(o) { 関数F(){} F.プロトタイプ = o; 新しいF()を返す } 関数 inheritPtototype(サブタイプ、スーパータイプ){ var prototype = object(superType.prototype) // オブジェクトを作成 prototype.constructor = subType // オブジェクトを拡張 subType.prototype = prototype // オブジェクトを指定 } 関数SuperType(名前){ this.name = 名前 this.colors = ['赤', '白'] } SuperType.prototype.sayName = function(){ console.log(この名前) } 関数 SubType(名前,年齢){ SuperType.call(これ、名前) this.age = 年齢 } 継承Ptototype(サブタイプ、スーパータイプ) SubType.prototype.sayAge = function(){ コンソールログ(this.age) } var インスタンス = 新しいサブタイプ ('ccc'、18) instance.sayName() // --> ccc instance.sayAge() // --> 18 console.log(インスタンス) コンソールによって出力される構造: 詳細図: この例の効率性は、SuperType コンストラクターを 1 回だけ呼び出すため、SubType.prototype に不要な冗長プロパティが作成されないことです。同時に、プロトタイプ チェーンは変更されないため、instanceof と isPrototypeOf() は引き続き正常に使用できます。これは多くの大企業が採用している継承方法でもあります。 以上がjsで継承を実装する5つの方法の詳細です。js継承の詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。 以下もご興味があるかもしれません:
|
<<: Linux ファイルシステムの説明: ext4 以降
>>: テーブルパーティションとパーティション分割とは何ですか?MySqlデータベースパーティションとテーブルパーティション分割方法
以下のように表示されます。 1. ssh -v -p [ポート番号] [ユーザー名]@[IPアドレス...
目次序文Viteプロジェクトを作成する改修プロジェクトディレクトリの規則その他の構成序文毎日鳩、火ば...
1. Get はサーバーからデータを取得するために使用され、Post はサーバーにデータを渡すために...
国慶節の休暇後、Windows アップデート後に VMware 仮想マシンが開けなくなり、「VMwa...
MySQL を初めて学ぶときは、区切り文字の本当の目的を理解していないかもしれません。区切り文字は、...
では、ドメイン名を登録して仮想ホストを購入した後、IE でドメイン名を入力して Web サイトを開く...
1.1 はじめにスロークエリログを有効にすると、MySQL は指定された時間を超えるクエリステートメ...
序文ロックの範囲に応じて、MySQL のロックは、グローバル ロック、テーブル ロック、行ロックに大...
VNC はリモート デスクトップ プロトコルです。 VNC を使用して Ubuntu 20.04 を...
1. scale() メソッドズームとは「縮小」と「拡大」を意味します。 CSS3 では、scal...
目次継承ES5 プロトタイプ継承ES6 クラス継承両者の違いES5プロトタイプ継承の内部実装ES6 ...
1. transform 属性を使用して、画像を拡大せずに表示します (パスの問題は必要に応じて修正...
コンテンツオーバーフローとは何ですか?実際、テキストが大量にある場合、コンテンツ領域がそれだけの長さ...
目次1. タスクキュー2. 混乱を招く問題を説明する1. setTimeout(f1,0)とは何です...
1. ユーザーを作成して承認するMySQL 8.0 では、ユーザーの作成と認証が以前とは異なります...