ES6 では、class キーワードを使用してクラスを定義し、extends キーワードを使用してクラスを継承します。スーパー メソッドは、親クラスの「this」オブジェクトを取得するために、サブクラスのコンストラクター内で呼び出す必要があります。スーパーを呼び出すときに、パラメーターを親コンストラクターに渡すことができます。サブクラスは、スーパー オブジェクトを通じて親クラスのプロパティとメソッドを直接使用したり、同じ名前のプロパティやメソッドを通じて親クラスの定義をオーバーライドしたりできます。
class Father { constructor () { this.surname = '王' this.money = Infinity } sayName () { console.log(`My surname is ${this.surname}.`) } } class Son extends Father { constructor (firstname) { super() this.firstname = firstname } sayName () { console.log(`My name is ${super.surname}${this.firstname}.`) } sayMoney () { console.log(`I have ${this.money} money.`) } } let Sephirex = new Son('撕葱') Sephirex.sayName() Sephirex.sayMoney()
ES6 のクラスと継承は、基本的にプロトタイプを使用して実装された構文です。クラスで定義されたメソッドは、コンストラクター メソッドでのメソッドの定義と同等であり、スーパー メソッドの定義はメソッドの定義と同等です。サブクラス内で親クラスのコンストラクターを呼び出します。 ES5 での継承の実装について引き続き説明しましょう。
プロトタイプ チェーンの継承の基本パターンは、サブタイプのプロトタイプ オブジェクトが親タイプのインスタンスを指すようにし、そのプロトタイプのメソッドを拡張することです。
function Person (name) { this.name = name this.likes = ['apple', 'orange'] } Person.prototype.sayName = function () { console.log(this.name) } function Worker () { this.job = 'worker' } Worker.prototype = new Person() Worker.prototype.sayJob = function () { console.log(this.job) } let Tom = new Worker() let Jerry = new Worker() Tom.likes.push('grape') console.log(Jerry.likes) // [ 'apple', 'orange', 'purple' ]
原則: 前の記事では、__proto__ とプロトタイプについて説明しました。サブクラスのインスタンスには __proto__ ポインターがあり、そのコンストラクターのプロトタイプ オブジェクトを指します。サブクラスのコンストラクターのプロトタイプは親クラスのインスタンスを指し、親クラスのインスタンス内の __proto__ は親クラスのコンストラクターのプロトタイプを指す…このようにしてプロトタイプチェーンが形成されます。
親クラスの参照型プロパティがコンストラクターで定義されている場合でも、それらは子クラスのインスタンスによって共有されることに注意してください。これは、サブクラスのコンストラクターのプロトタイプが実際には親クラスのインスタンスであるため、親クラスのインスタンス プロパティが当然サブクラスのプロトタイプ プロパティとなり、参照型値のプロトタイプ プロパティがインスタンス間で共有されるためです。
プロトタイプ チェーンのもう 1 つの問題は、すべてのオブジェクト インスタンスに影響を与えずに親クラスのコンストラクターにパラメーターを渡す方法がないことです。上の例のように、 Worker.prototype = new Person() を使用してサブクラス プロトタイプを親クラス インスタンスにポイントする場合、初期化パラメータが渡されると、すべてのサブクラスのインスタンス名属性がパラメータとして渡されます。ここでパラメーターが渡されない場合、後で親クラスのコンストラクターにパラメーターを渡す方法はありません。したがって、プロトタイプ チェーン継承パターンが単独で使用されることはほとんどありません。
コンストラクターを借用すると、参照型属性が共有される問題を解決できます。コンストラクターのいわゆる「借用」とは、サブクラスのコンストラクター内で親クラスのコンストラクターを呼び出すことです。関数内の this のポインターは、関数が定義されている場所とは何の関係もないことを忘れないでください。呼び出される場所のみ。 ES6 サブクラス コンストラクターでスーパー メソッドを呼び出すのと同様に、call または apply を使用してサブクラス インスタンスで親クラスのコンストラクターを呼び出し、親クラスのプロパティとメソッドを取得できます。
function Person (name) { this.name = name this.likes = ['apple', 'orange'] } function Worker (name) { Person.call(this, name) this.job = 'worker' } let Tom = new Worker('Tom') Tom.likes.push("grape") let Jerry = new Worker('Jerry') console.log(Tom.likes) // [ 'apple', 'orange', 'grape' ] console.log(Jerry.likes) // [ 'apple', 'orange' ]
コンストラクターを単純に使用する場合の問題は、関数が再利用できないことと、サブクラスが親クラスのプロトタイプの属性とメソッドを取得できないことです。
組み合わせ継承は、コンストラクターを借用してインスタンスのプロパティを定義し、プロトタイプ チェーン共有メソッドを使用します。継承の結合は、プロトタイプ チェーン モードと借用したコンストラクターを結合することで、両方の長所を活用し、それぞれの欠点を補います。これは、js で最も一般的に使用される継承モードです。
function Person (name) { this.name = name this.likes = ['apple', 'orange'] } Person.prototype.sayName = function () { console.log(this.name) } function Worker (name, job) { Person.call(this, name) // 第二次调用 Person() this.job = job } Worker.prototype = new Person() // 第一次调用 Person() Worker.prototype.constructor = Worker Worker.prototype.sayJob = function () { console.log(this.job) } let Tom = new Worker('Tom', 'electrician') Tom.likes.push('grape') console.log(Tom.likes) // [ 'apple', 'orange', 'grape' ] Tom.sayName() // Tom Tom.sayJob() // electrician let Jerry = new Worker('Jerry', 'woodworker') console.log(Jerry.likes) // [ 'apple', 'orange' ] Jerry.sayName() // Jerry Jerry.sayJob() // woodworker
結合継承には欠点がないわけではありません。それは、継承プロセスで親クラスのコンストラクターが 2 回呼び出されるということです。 Person コンストラクターが初めて呼び出されるとき、Worker.prototype は 2 つの属性 (name と likes) を取得します。Worker コンストラクターが呼び出されるとき、再び Person コンストラクターが呼び出され、今回はインスタンス属性の name と likes が直接作成されます。 、プロトタイプ内の同じ名前の 2 つのプロパティをカバーします。
次のオブジェクト関数は、Douglas Crockford の記事に記録されています。オブジェクト関数内では、最初に一時コンストラクターが作成され、次に渡されたオブジェクトがこのコンストラクターのプロトタイプとして使用され、最後にこの一時型の新しいインスタンスが返されます。基本的に、object() は、渡されたオブジェクトの浅いコピーを実行します。この継承方法は、親タイプのプロパティとメソッドをサブタイプにコピーし、それぞれのプロパティとメソッドをサブタイプに追加することと同じです。
このメソッドは、参照型値のプロパティも共有します。
function object(o){ function F(){} F.prototype = o; return new F(); } let Superhero = { name: 'Avenger', skills: [], sayName: function () { console.log(this.name) } } let IronMan = object(Superhero) IronMan.name = 'Tony Stark' IronMan.skills.push('fly') let CaptainAmerica = object(Superhero) CaptainAmerica.name = 'Steve Rogers' CaptainAmerica.skills.push('shield') IronMan.sayName() // Tony Stark console.log(IronMan.skills) // [ 'fly', 'shield' ]
ES5 は Object.create() メソッドを使用してプロトタイプの継承を標準化します。このメソッドは 2 つのパラメータを受け入れます。新しいオブジェクトのプロトタイプとして使用されるオブジェクトと、(オプションで) 新しいオブジェクトの追加プロパティを定義するオブジェクトです。 1 つの引数が渡された場合、Object.create() は object() メソッドと同じように動作します。 Object.create() メソッドの 2 番目のパラメーターの形式は、Object.defineProperties() メソッドの 2 番目のパラメーターと同じです。
let CaptainAmerica = Object.create(Superhero, { name: { value: 'Steve Rogers', configurable: false } })
寄生継承は、継承プロセスをカプセル化した単なるファクトリ関数です。メソッドはオブジェクト上で直接定義されるため、寄生継承によって追加されたメソッドは再利用できません。
function inherit(parent){ var clone = Object.create(parent) clone.name = 'hulk' clone.sayHi = function(){ console.log("hi") } return clone } let Hulk = inherit(Superhero) Hulk.sayName() // hulk Hulk.sayHi() // hi
前述したように、結合継承はjsで最もよく使われる継承方法ですが、親クラスのコンストラクターが2回呼び出されるという欠点があります。寄生構成継承はこの問題を解決でき、参照型の値を含むオブジェクトにとって最も理想的な継承方法と考えられています。
寄生結合継承の基本的な考え方は、サブクラスのプロトタイプを指定するために親クラスのコンストラクターを呼び出す必要はなく、必要なのは親クラスのプロトタイプのコピーだけであるということです。寄生構成継承は、コンストラクターを借用してプロパティを継承し、寄生継承を使用して親クラスのプロトタイプを継承します。
以上がjsの継承メソッドにはどのようなものがあるのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。