ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript プロトタイプの継承についての深い理解

JavaScript プロトタイプの継承についての深い理解

黄舟
黄舟オリジナル
2017-02-21 11:19:19880ブラウズ



継承の本質: 再利用

JavaScript でのプロトタイプの継承について議論する前に、なぜ継承が必要なのかを考えたほうがよいでしょうか?

2 つのオブジェクトがあり、そのうちのいくつかは同じプロパティを持ち、もう 1 つは異なるプロパティを持っているというシナリオを考えてみましょう。通常、優れた設計ソリューションは、同じロジックを抽出して再利用することです。

2 人の学生 xiaoMing liLei を例に挙げます。クラスメイトの二人はそれぞれ名前を持っており、自己紹介をします。プログラムオブジェクトとして抽象化すると以下のように表現できます。

var xiaoMing = {
  name : "xiaoMing",
  hello : function(){
    console.log( 'Hello, my name is '+ this.name + '.');
  }
}

var liLei = {
  name : "liLei",
  hello : function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
}

Java を使用したことのある学生は、この問題を解決するためにオブジェクト指向を使用することを最初に考えるかもしれません。 Person クラスを作成し、xiaoMing と liLei という 2 つのオブジェクトをインスタンス化します。 ES6 には、Java のクラスに似た概念、 class もあります。

以下では ES6 構文を使用し、オブジェクト指向の考え方を使用して上記のコードを再構築します。

class Person {
  constructor(name){
    this.name = name
  }

  hello(){
    console.log(this.name);
  }
}

var xiaoMing = new Person('xiaoMing');
var liLei = new Person('liLei');

クラスを使用してオブジェクトを作成すると、再利用の目的が達成されることがわかります。このロジックは、2 つ以上のオブジェクトが同様の構造と機能を持っている場合、テンプレートを抽象化し、そのテンプレートに従って複数の同様のオブジェクトをコピーできるというロジックに基づいています。

同じ設計図を何度も再利用して多数の自転車を製造する自転車メーカーと同じように、クラスを使用してオブジェクトを作成します。

もちろん、再利用の問題には複数の解決策があります。従来のオブジェクト指向クラスは、解決策の 1 つにすぎません。今度は、再利用の問題を別の角度から解決する主人公「プロトタイプ継承」が登場します。

プロトタイプ継承の原理

プロトタイプオブジェクト

JavaScript のオブジェクトは、通常のプロパティのコレクションとプロトタイプ プロパティの 2 つの部分で構成されます。

var o = {
  a : 'a',
  ...
  __proto__: prototypeObj
}

通常の属性は を参照し、プロトタイプ属性は __proto__ を参照します。これは仕様の一部ではありませんでしたが、その後、chrome は __proto__ を通じて言語の基礎となるプロパティを公開し、徐々に誰もが受け入れ、ES6 仕様に追加されました。 o.__proto__prototypeObj の値は プロトタイプ オブジェクト です。プロトタイプ オブジェクトは実際には通常のオブジェクトです。プロトタイプ オブジェクトと呼ばれる理由は、それがプロトタイプ属性によって指定される値だからです。

プロトタイプ オブジェクトは、他のオブジェクトとそのプロパティを共有するという、通常のオブジェクトにはない機能があるため、特別です。

ES6 仕様では、次のように定義されています:

object that provides shared properties for other objects

プロパティ読み取り操作

元の例に戻って、プロトタイプ継承を使用して再利用を実現する方法を確認してください。

var prototypeObj = {
  hello: function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
  // ...
}

var xiaoMing = {
  name : "xiaoMing",
  __proto__ : prototypeObj
}

var liLei = {
  name : "liLei",
  __proto__ :  prototypeObj
}

xiaoMing.hello(); // Hello, my name is xiaoMing.
liLei.hello();  // Hello, my name is liLei.

xiaoMing liLei オブジェクトは直接 hello 属性 (メソッド) を持っていませんが、属性を読み取る (メソッドを実行する) ことはできるのはなぜでしょうか。

数学の宿題をしているときに、やり方がわからない難しい問題に遭遇するシナリオを想像してください。そして、あなたには数学が得意な良い兄弟がいて、彼に助けを求めてこの問題を解決します。

xiaoMing オブジェクトには hello 属性はありませんが、優れた兄弟であるprototypeObj があります。属性読み取り操作の場合、xiaoMing で hello 属性が見つからない場合は、その兄弟であるprototypeObj に問い合わせます。したがって、hello メソッドが実行されます。

プロトタイプ チェーン

は、依然として数学の問題を行う例です。あなたの数学の質問は難しいので、お兄さんは答えを持っていません。別のクラスメートに質問することをお勧めします。そうすれば、答えが見つかるか、尋ねる人がいなくなるまで、もう質問する必要はありません。まるで目に見えない鎖があなたとクラスメートを結びつけているようです。

JS では、読み取り操作は __proto__ を通じてレイヤーごとにチェーンされます。これはプロトタイプ チェーンと呼ばれます。

var deepPrototypeObj = {
  hello: function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
  __proto__ : null
}

var prototypeObj = {
  __proto__ : deepPrototypeObj
}

var xiaoMing = {
  name : "xiaoMing",
  __proto__ : prototypeObj
}

var liLei = {
  name : "liLei",
  __proto__ :  prototypeObj
}

xiaoMing.hello(); // Hello, my name is xiaoMing.
liLei.hello();  // Hello, my name is liLei.

プロトタイプ継承の実装

上記の例では、__proto__ 属性値を直接変更することでプロトタイプ継承を実装しています。ただし、実際の運用環境では、Object.create() メソッドを使用することもできます。

Object.create() メソッドを呼び出すと、新しいオブジェクトが作成され、渡される最初のパラメーターとしてオブジェクトのプロトタイプ オブジェクトが指定されます。

上記の例を変更してみましょう。

var prototypeObj = {
  hello: function(){
    console.log( 'Hello, my name is '+ this.name  + '.');
  }
  // ...
}

var xiaoMing = Object.create(prototypeObj);
var liLei = Object.create(prototypeObj);

xiaoMing.name = "xiaoMing";
liLei.name = "liLei";

xiaoMing.hello(); // Hello, my name is xiaoMing.
liLei.hello();  // Hello, my name is liLei.

You-Dont-Know-JS の作者は、このプロトタイプ継承の実装に OLOO (objects-linked-to-other-objects) という非常に楽しい名前を付けました。この実装の利点は、概念をまったく使用しないことです。クラスのはオブジェクトのみなので、JavaScript の特性と非常に一致しています。

JSにはクラスが存在せず、オブジェクトのみであるためです。

残念ながら、クラスを好むプログラマーが多すぎるため、クラスの概念は ES6 で追加されました。次回はJSにおけるクラスの実装原理についてお話します

概要

クラスは再利用の目的を達成するためにオブジェクトを作成します。このロジックは、2 つ以上のオブジェクトが類似した構造と機能を持ち、テンプレートを抽象化し、そのテンプレートに従って複数の類似したオブジェクトを作成できるというロジックに基づいています。それは、自転車メーカーが同じ設計図を何度も再利用してたくさんの自転車を製造するようなものです。

プロトタイプ継承を使用すると、再利用の目的を達成することもできます。このロジックは、2 つ以上のオブジェクトが共有属性を持っているというもので、特別なプロトタイプ属性を使用して、共有属性を別の独立したパブリック オブジェクトに抽象化し、属性の読み取り (書き込み) を行うことができます。 ) ルールをたどって検索して、属性の共有を実現します

上記は JavaScript プロトタイプの継承について詳しく説明しています。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。