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

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

推薦する

Vue のデータ応答性に関する詳細な理解

目次1. ES 構文のゲッターとセッター2. ES構文でのdefineProperty 3. Vue...

MySQL 5.7.13 のインストールと設定方法の Mac でのグラフィック チュートリアル

MySQL 5.7.13 Mac用インストールチュートリアル、非常に詳細で、以下のように記録されてい...

Ubuntu 18.04 のログインループ/ブートインターフェイスで停止/グラフィカルインターフェイスに入ることができない問題を解決する方法

原因: NVIDIA グラフィック カード ドライバーが破損している解決:コマンドラインモードで再起...

Maxwell を使用して MySQL データをリアルタイムで同期する方法

目次マクスウェルについてMaxwellの設定と使用1. Maxwellインストールパッケージをダウン...

Linux で TCP 接続の最大数をテストする方法

序文TCP サーバの最大同時接続数に関して、「ポート番号の上限が 65535 であるため、TCP サ...

MySQL 8.x msi バージョンのインストール チュートリアル (画像とテキスト付き)

1. MySQLをダウンロードする公式サイトのダウンロードアドレス https://dev.mys...

Echarts バー水平棒グラフのサンプルコード

目次横棒グラフデータとスタイルを動的に更新するeChartsの幅と高さの適応の問題を解決する縦棒グラ...

JavaScript でプロトタイプ パターンを実装する方法

概要プロトタイプ パターンは、プロトタイプ インスタンスによって作成されるオブジェクトの型を指し、こ...

WindowsにOpenSSLをインストールし、OpenSSLを使用して公開鍵と秘密鍵を生成します。

1. OpenSSL公式サイト公式ダウンロードアドレス: https://www.openssl....

フロントエンド JavaScript ハウスキーパー package.json

目次1. 必須属性1. 名前2. バージョン2. 説明情報1. 説明2. キーワード3. 著者4. ...

MYSQL の COLLATE とは何ですか?

序文MySQL で show create table <tablename> コマンド...

Linux での vi (vim) の新しい使い方のまとめ

私は数年間 vi エディタを使ってきましたが、実用的な用途で使ったことはありませんでした。今日 Py...

MySQL スケジュールタスク (EVENT イベント) を詳細に設定する方法

目次1. イベントとは何ですか? 2. 「イベント」機能を有効にする1. 機能が有効になっているかど...

HTML ハイパーリンク タグ_Powernode Java アカデミー

HTML を学習したり使用したりしたことがある人なら、<a> タグについてよく知っている...

Vueは商品詳細ページの商品タブ機能を実装します

この記事の例では、商品詳細ページ機能を実現するためのVueの商品タブの具体的なコードを参考までに共有...