JS上級編ES6の6つの継承方法

JS上級編ES6の6つの継承方法

序文:

継承は、オブジェクト指向プログラミングでよく話題になります。ECMAScript6 以前は、 JavaScriptの継承は非常に複雑でした。継承にはさまざまな種類がありました。基本的に、すべての継承はプロトタイプ チェーンECMAScript6切り離せないものでした。ES6 ES6新しく追加されたextendsキーワードも、プロトタイプ チェーンを通じて継承を実装しますが、構文は比較的単純です。

プロトタイプチェーンの内容については、前回の記事の2つの画像を参照してプロトタイプチェーンを理解することができます。

この記事では、ECMAScript6 以前に継承がどのように実装されていたかを紹介します。

1. プロトタイプチェーン継承

プロトタイプ チェーン継承の助けを借りて、プロトタイプのポイントを変更することが本質です。実装コードは次のとおりです。

関数 ParentClass() {
  this.name = '一碗の周'
}
ParentClass.prototype.getName = 関数 () {
  this.name を返す
}

// 将来的に親クラスを継承するサブクラスを定義する function ChildClass() {}

// * 子クラスのプロトタイプを親クラスのインスタンスにポイントします。子クラスは親クラスのインスタンスの内容を持ちます。ChildClass.prototype = new ParentClass()

// サブクラスをインスタンス化します var child = new ChildClass()

console.log(child.getName()) // イーワン・ゾウ

上記のコードは次のように表されます。

図の赤い線は、コンストラクタとインスタンス オブジェクト間のプロトタイプ チェーンを表しています。継承は、このプロトタイプ チェーンの関係を通じて実現されます。

この方法で継承を実装することの欠点の 1 つは、複数のインスタンスによってプロトタイプ オブジェクトの内容が共有され、内容が互いに影響し合うことです。テスト コードは次のとおりです。

関数 ParentClass() {
  this.colors = ['赤', '青', '緑']
}
関数 ChildClass() {}

ChildClass.prototype = 新しい ParentClass()

var child1 = 新しいChildClass()
var child2 = 新しいChildClass()
console.log(child1.colors) // [ '赤', '青', '緑' ]

child2.colors.push('黒')
console.log(child2.colors) // [ '赤', '青', '緑', '黒' ]

console.log(child1.colors) // [ '赤', '青', '緑', '黒' ]

テスト コード内のchild1変更されませんが、 child1が変更されると、 child1の値も変更されます。

2. コンストラクタによる継承

コンストラクタを使用したいわゆる継承 (一部の資料では擬似オブジェクトまたは古典的継承とも呼ばれます) は、Function.call() または Function.apply() メソッドを使用して、子オブジェクトを介して親クラスのコンストラクタを呼び出すことによって継承を完了することです。

サンプルコードは次のとおりです。

関数親() {
  // 親オブジェクト this.parent = 'parent'
}

Parent.prototype.name = 'Yiwan Zhou' // Parent親オブジェクトのプロトタイプにプロパティを追加します function Child() {
  // 子オブジェクト this.child = 'child'

  Parent.call(this) // call() または apply() メソッドを使用して親コンストラクターを呼び出し、継承を実装します。
}

定数child = 新しいChild()

console.log(子)

console.log(child.name) // undefined // 親クラスのプロトタイプを継承しません

実行フローは以下のとおりです。

この方法を使用する利点は、参照型のインスタンスがすべてのオブジェクトで共有されることを回避できることです。欠点は、すべてのメソッドがコンストラクターで定義されるため、プロトタイプ オブジェクトを継承せず、各オブジェクトがインスタンス化された後にこれらのメソッドが再作成されるため、関数の再利用は言うまでもなく、メモリ領域が占有されることです。

3. 組み合わせ継承

これまでに習得した 2 つの継承方法には、どちらも欠点があります。プロトタイプ継承に基づく継承方法では、インスタンス化されたすべてのオブジェクトがプロトタイプのメソッドとプロパティを共有します。変更があれば、すべてが変更されます。ただし、プロトタイプ プロパティはコンストラクター継承を通じて継承することはできません。そこで、プロトタイプベースの継承方式とコンストラクタを利用した継承方式を組み合わせ、本質だけを取り、不要な部分を取り除く継承方法である結合継承が生まれました。

結合継承を実装する基本的な考え方は次のとおりです。

  • プロトタイプのプロパティとメソッドを継承するには、プロトタイプ チェーンまたはプロトタイプ継承を使用します。
  • インスタンス オブジェクト プロパティの継承は、構造コンストラクターを通じて実現されます。

このように、プロトタイプにメソッドを定義することで関数の再利用が実現され、各オブジェクトが独自のプロパティを持つことが保証されます。

サンプルコードは次のとおりです。

// 親オブジェクト関数 Parent() {
  this.parent = '親'
}
// Parent 親オブジェクトのプロトタイプにプロパティを追加します Parent.prototype.name = 'Yiwan Zhou'
//子オブジェクト関数Child() {
  this.child = '子'
  // 継承を実装するには、call() または apply() メソッドを使用して親コンストラクターを呼び出します。
  親.call(これ)
}
// コンストラクタを継承しないプロトタイプオブジェクトの問題を解決する Child.prototype = Parent.prototype

定数child = 新しいChild()
console.log(child.name) // イーワン・ゾウ

4. プロトタイプの継承

Object.create() メソッドを使用して、一種の継承を実装できます。サンプル コードは次のとおりです。

var 人 = {
  名前:「周の一杯」
  友人: ['張三'、'李斯'、'王武']、
}

var anotherPerson = Object.create(人)
anotherPerson.name = '甘いボウル'
anotherPerson.friends.push('赵六')

console.log(person.friends) // [ '張三', '李四', '王武', '趙劉' ]

この方法の欠点は最初の方法と同じです。つまり、複数のインスタンスによってプロトタイプ オブジェクト上のコンテンツが共有され、コンテンツが互いに影響し合うことになります。

5. 寄生遺伝

寄生継承の基本は、オブジェクトを拡張し、プロトタイプ継承に基づいてコンストラクターを返すことです。サンプルコードは次のとおりです。

var 人 = {
  名前:「周の一杯」
  友人: ['張三'、'李斯'、'王武']、
}

関数createAnother(オリジナル) {
  var clone = Object.create(original) // object() 関数を呼び出して新しいオブジェクトを作成します clone.sayMe = function () {
    // 何らかの方法でオブジェクトを強化する}
  return clone // このオブジェクトを返す }

var anotherPerson = createAnother(人)
別の人.sayMe()

その欠点はネイティブ継承の欠点と同じです。

6. 寄生的組み合わせ継承

この継承方法は、コンストラクタと寄生継承を介してパラメータを渡すことによって実装されます。サンプルコードは次のとおりです。

関数 inheritPrototype(ChildClass, ParentClass) {
  var prototype = Object.create(ParentClass.prototype) // オブジェクトを作成し、親クラス プロトタイプのコピーを作成します // 作成された親クラス プロトタイプのコピーのコンストラクターを変更し、子クラス プロトタイプをこのクラスにポイントして、親クラスとは無関係なクラスを形成します prototype.constructor = ChildClass
  ChildClass.prototype = プロトタイプ
}

// 親クラスはインスタンスプロパティとプロトタイププロパティを初期化します function ParentClass(name) {
  this.name = 名前
  this.colors = ['赤', '青', '緑']
}
ParentClass.prototype.sayName = 関数 () {
  console.log(この名前)
}

// コンストラクターを使用して、拡張サブクラス インスタンス プロパティを渡します (パラメーターの受け渡しをサポートし、改ざんを回避します)
関数 ChildClass(名前, 年齢) {
  //親クラスのプロパティをすべてコピーします ParentClass.call(this, name)
  this.age = 年齢
}

// 親クラスのプロトタイプを子クラスにポイントします。inheritPrototype(ChildClass, ParentClass)

// サブクラスのプロトタイププロパティを追加する ChildClass.prototype.sayAge = function () {
  コンソールログ(this.age)
}

var instance1 = new ChildClass('一碗周', 19)
var instance2 = new ChildClass('甘いボウル', 18)

インスタンス1.colors.push('黒')
console.log(instance1.colors) // [ '赤', '青', '緑', '黒' ]
instance1.sayName() // 一杯の Zhouinstance2.colors.push('yellow')
console.log(instance2.colors) // [ '赤', '青', '緑', '黄' ]

この例は、 ParentClassコンストラクターを 1 回だけ呼び出すため、 ChildClass.prototypeに不要な冗長プロパティが作成されることがなくなり、効率的です。同時に、プロトタイプ チェーンは変更されないため、 instanceofisPrototypeOf()。

理解できない場合は、読み続けてください。まず、以下に示すように、コア コードを抽出します。

上の図はコアコードを示しています。ParentClass とChildClassのデフォルトのプロトタイプ チェーンがどのようになっているかParentClass見てみましょう。

写真は以下のとおりです。

次に、inheritPrototype() メソッドを呼び出して、ChildClass のプロトタイプを変更します。解析図は次のようになります。

最後に、サブクラスのcall()メソッドを介して親クラスを呼び出して、親クラス自身のプロパティcopyことを忘れないでください。これにより、比較的完全な継承メソッドが実現されます。

結論:

この記事ではextendsキーワード以外の 6 つの継承方法を紹介します。 ECMAScript6ではclassキーワードとクラスに関する内容がすべて追加されましたが、本文で紹介した継承方法はあまり使用されなくなりました。

ただし、 ECMAScript6追加された新しいクラスは、本質的には構文上の糖衣です。JavaScript で継承について話すときは、必ず class キーワードが必要です。

以上で、JS 上級編 ES6 の 6 つの継承方法についての記事は終了です。ES6 の 6 つの継承方法についてさらに詳しく知りたい方は、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • 1 つの記事で JavaScript の継承を理解する
  • js の一般的な継承方法 6 つの概要
  • JS の 6 つの継承方法とその長所と短所
  • ネイティブ JavaScript 継承方法とその長所と短所の詳細な説明
  • jsの継承の6つの方法を詳しく解説
  • JavaScriptで継承を実装するいくつかの方法
  • 6 つの JavaScript 継承方法とその長所と短所 (まとめ)
  • JS で継承を実装する一般的な方法の例
  • JavaScriptで複数の継承メソッドを共有する

<<:  CSS を使用してテクスチャ付きグラデーション背景画像を記述するためのサンプル コード

>>:  ラベルタグを使用してテキストをクリックしてラジオボタンを選択します

推薦する

アプレットにおけるwx.getUserProfileインターフェースの具体的な使用

最近、WeChatミニプログラムは、監査ミニプログラムのwx.loginおよびwx.getUserI...

MySQL で UTF-8 エンコーディングを使用しないのはなぜですか?

MySQL UTF-8 エンコーディングMySQL は 2003 年のバージョン 4.1 から U...

MySQL における count(*)、count(1)、count(col) の違いのまとめ

序文count 関数は、テーブルまたは配列内のレコードをカウントするために使用されます。count(...

Windows 10 Home EditionにDockerをインストールする方法を教えます

Redisの本やSpring Cloud Alibabaの本を執筆した際に、一部の分散コンポーネント...

CSSブレンドモードとSVGを使用して、製品画像の色を動的に変更します。

数日前、Codepen で @Kyle Wetton が書いた、CSS ブレンディング モードと S...

Windows 10 での Tomcat のインストールと展開に関する詳細なチュートリアル

目次1 Java環境の設定2 tomcatのインストールと展開Tomcat をインストールして展開す...

MYSQL開発パフォーマンス調査:バッチデータ挿入の最適化方法

1. どのような問題に直面しましたか?標準 SQL では、通常、次の SQL 挿入ステートメントを記...

Vue3+Vue-cli4 プロジェクトで Tencent スライダー検証コードを使用する方法

導入:従来の画像検証コードと比較して、スライダー検証コードには次の利点があります。サーバーは検証コー...

HTML の META タグの使用に関するヒントの例

HTML メタタグHTML メタタグは、Web ページのコンテンツに関する情報をブラウザや検索エンジ...

CSS の overflow: hidden の使い方 (オーバーフローの非表示とフロートのクリア)

オーバーフロー非表示指定された高さを超えるテキストや画像情報を非表示にすることを意味します。 <...

システム エラー 1067 のため、MySQL 5.6 解凍バージョン サービスを開始できません

今日午後ずっと私を悩ませたバグを記録する半月前から始めましょう。それから.................

ウェブデザインとは何か

<br />元の記事: http://www.alistapart.com/articl...

スクラッチ宝くじの例を実現する JavaScript キャンバス

この記事では、スクラッチ効果を実現するためのJavaScriptキャンバスの具体的なコードを参考まで...

マウス追従ゲームを実現するjs

この記事では、マウス追従ゲームを実装するためのjsの具体的なコードを参考までに共有します。具体的な内...

MySQLシリーズのMariaDBサーバーのインストール

目次チュートリアルシリーズ1. yumパッケージマネージャーを使用してMariaDBサーバーをインス...