オープニング
「厳密な」意味では、JavaScript は真のオブジェクト指向言語ではありません。このステートメントの理由は、一般に、弱い型付け言語としての JavaScript は、Java や C# などの強力な言語の継承メソッドとは大きく異なるため、デフォルトでは非主流のオブジェクト指向メソッドであり、この本では、この言語を「完全なオブジェクト指向ではない」言語と説明しています。実際のところ、メソッドは重要ではなく、オブジェクト指向の考え方を持っているかどうかが重要だと個人的に感じています。JavaScript はオブジェクト指向言語ではないと言っている人は、JavaScript の継承メソッドを深く勉強していない可能性があります。この記事はコミュニケーションのために書きました。
継承を実装するために JavaScript を使用する必要がある理由
初期の PC マシンのパフォーマンスはお世辞にも優れていません。すべての負荷はサーバー側にあり、クライアントのブラウザは単なる飾りです。当時は人気のあったテーブル レイアウトと電話回線によるインターネット アクセスも相まって、Web ページの閲覧は非常に遅かったのですが、現在ではインターネット時代が急速に発展しており、パーソナル コンピュータのハードウェアは大幅に改良されており、クライアント ブラウザのパフォーマンスも非常に残念なものとなっています。 Web 開発のモデルも静かに変化しています。サーバーは以前ほど「ハード」ではなくなり、その代わりにブラウザーができるだけ多くのタスクを引き受けるようになるだけでなく、各クライアントに負担がかかります。企業 コストの節約により、Web フロントエンド開発がより興味深いものになります。ますます多くのフロントエンド フレームワークが登場し、さらに多くのフロントエンド MVC フレームワークが登場しています。この文脈において、JavaScript の役割は単純な検証を行ったり、リクエストを送信したり、DOM を操作したりするだけではありません。フロントエンドのルーティングやビジネス層など、より多くの役割を果たす必要があり、JavaScript は多くの論理的な処理を実行する必要があります。タスクには、フロントエンド データ (モデル) の抽象化が含まれており、オブジェクト指向の思考を使用することによってのみ、抽象化されたデータを適切に処理できるため、ここでは継承が非常に重要です。
単純なニーズから始めましょう
ここで、基本的な属性である名前と年齢を持つ person という名前のモデルを抽出します。デフォルトでは、全員が話すことができるため、各インスタンスのプロトタイプ オブジェクトに発話機能が配置されます。さて、人間の場合は、人の基本属性を継承し、これに基づいて独自の固有の属性を追加する必要があります。
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.say = function(){ console.log('hello, my name is ' + this.name); }; function Man() { //my own properties }
以下では、主流の継承メソッドをいくつか紹介します。
1. プロトタイプチェーンの継承
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.say = function(){ console.log('hello, my name is ' + this.name); }; function Man() { } Man.prototype = new Person('pursue'); var man1 = new Man(); man1.say(); //hello, my name is pursue var man2 = new Man(); console.log(man1.say === man2.say);//true console.log(man1.name === man2.name);//true
この継承メソッドは非常に直接的であり、Person のすべての属性メソッド (インスタンスとプロトタイプ) を取得するために、親クラスのインスタンス new Person('pursue') がサブクラスのプロトタイプに直接割り当てられます。 、サブクラス クラス インスタンス man1 と man2 自体は完全に空のオブジェクトです。すべての属性とメソッドはプロトタイプ チェーン上で見つかる必要があるため、見つかった属性とメソッドは同じです。
したがって、プロトタイプチェーンの継承を直接使用することは非現実的です。
2. コンストラクターの継承を使用します
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.say = function(){ console.log('hello, my name is ' + this.name); }; function Man(name, age) { Person.apply(this, arguments); } //Man.prototype = new Person('pursue'); var man1 = new Man('joe'); var man2 = new Man('david'); console.log(man1.name === man2.name);//false man1.say(); //say is not a function
ここでは、サブクラスはコンストラクターで apply を使用して親クラスのコンストラクターを呼び出します。これは、少なくとも各インスタンスを直接使用するよりも、親クラスのプロパティを継承する効果を実現します。には独自のリソースがありますが、このメソッドは親クラスのインスタンス属性しか継承できないため、親クラスのすべての属性とメソッドを継承するには、プロトタイプ チェーンを変更する必要があります。したがって、結合継承方法が導入されます。
3. 組み合わせの継承
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.say = function(){ console.log('hello, my name is ' + this.name); }; function Man(name, age) { Person.apply(this, arguments); } Man.prototype = new Person(); var man1 = new Man('joe'); var man2 = new Man('david'); console.log(man1.name === man2.name);//false console.log(man1.say === man2.say);//true man1.say(); //hello, my name is joe
man1 と man2 のインスタンス属性は実際にはプロトタイプ属性をオーバーライドしますが、プロトタイプの Say メソッドをオーバーライドしないことに注意してください (プロトタイプがないため)。そのため、ここでは man1.say === man2 となります。 .say は引き続き true を返すため、すべてのインスタンスに共通するプロトタイプ プロパティをオーバーライドしないように注意してください。
4. 寄生組み合わせの継承
正直に言うと、次のフォームの名前はよくわかりませんが、確かに最も一般的で古典的な JavaScript 継承メソッドです。実際、プロトタイプ オブジェクトの構造を理解するだけで済みます:
function Person (name, age) { this.name = name; this.age = age; } Person.prototype.say = function(){ console.log('hello, my name is ' + this.name); }; function Man(name, age) { Person.apply(this, arguments); } Man.prototype = Object.create(Person.prototype);//a. Man.prototype.constructor = Man;//b. var man1 = new Man('pursue'); var man2 = new Man('joe'); console.log(man1.say == man2.say); console.log(man1.name == man2.name);
実際、寄生組み合わせ継承と上記の組み合わせ継承の違いは、サブクラス (a. および b.) のプロトタイプ オブジェクトを構築する方法のみです。ここでは Object.creat(obj) メソッドが使用されます。受信したオブジェクトを処理します。オブジェクトは次のように浅くコピーされます:
function create(obj){ function T(){}; T.prototype = obj; return new T(); }
したがって、a. 一般的な結合継承 (Man.prototype = new Person() など) のようにサブクラスのプロトタイプを直接コピーするのではなく、サブクラスのプロトタイプ オブジェクトを親クラスのプロトタイプ オブジェクトにうまく接続します。 ;)、これは属性の非常に暴力的な上書きにすぎません。寄生組み合わせ継承方法は、インスタンス属性とプロトタイプ属性を別々に継承するため、実装がより合理的です。
注: コード b. は、instanceof の結果を変更しませんが、コンストラクターが必要なシナリオではより厳密になります。
上記の Javascript のいくつかの継承メソッドの比較分析は、エディターが共有した内容です。参考にしていただければ幸いです。Script Home をサポートしていただければ幸いです。