JavaScript ES2015のオブジェクト継承のパターン
キーテイクアウト
-
ES2015を使用して、JavaScriptには、コードを清潔に保ち、階層の深さを最小限に抑え、重複コードを避けるためにクラスを定義するための特に構文があります。
- 複数の継承は、いくつかの古典的なOOP言語でサポートされている機能であり、複数のベースクラスから継承するクラスを作成できます。ただし、2つの親クラスが同じ方法を定義するダイヤモンドの問題に苦しんでいます。 メソッドのみを含む小さなクラスは、ダイヤモンドの問題をかわすために使用される別の戦略です。これらのクラスを拡張する代わりに、ミキシンは別のクラスに含まれています。 クラスの構文は、JavaScriptがクラスベースのOOP言語であるという幻想に与えていますが、そうではありません。ほとんどのアプローチでは、複数の継承を模倣するためにオブジェクトのプロトタイプを変更する必要があります。クラスの工場関数を使用することは、ミキシンを使用してクラスを作成するための許容可能な戦略です。
- 待望のES2015(以前はES6として知られていた)の待望の到着により、JavaScriptにはクラスを定義するための特に構文が装備されています。この記事では、クラスの構文を活用して、より小さな部品からクラスを作成できるかどうかを調べます。
- コードを清潔に保つには、階層の深さを最小限に抑えることが重要です。クラスをどのように分割するかについて賢くなることが役立ちます。大きなコードベースの場合、1つのオプションは、小さな部品からクラスを作成することです。クラスの作成。また、複製コードを避けるための一般的な戦略でもあります プレーヤーが動物の世界に住んでいるゲームを構築していると想像してください。友人は友人であり、他の人は敵対的です(私のような犬の人は、すべての猫が敵対的な生き物だと言うかもしれません)。動物を拡張するクラスの敵対的なクラスを作成するために、猫の基本クラスとして機能することができます。ある時点で、人間に害を及ぼすように設計されたロボットを追加することにしました。最初に行うことは、ロボットクラスを作成することです。現在、同様のプロパティを持つ2つのクラスがあります。たとえば、HostileanimalとRobotの両方が攻撃することができます。
- 敵対的な別のクラスまたはオブジェクトで敵意を何らかの形で定義できれば、それをロボットとして両方の猫と再利用することができます。さまざまな方法でそれを行うことができます

an
インターフェイスは、(タイプ化された)古典的なOOP言語の一般的な機能です。これにより、クラスに含まれる方法(および時にはプロパティ)を定義できます。そのクラスがそうでない場合、コンパイラはエラーを引き起こします。猫が攻撃()またはwalk()メソッドを持っていなかった場合、次のタイプスクリプトコードはエラーを引き起こします:
<span>class Animal(object): </span> <span>def walk(self): </span> <span># ... </span> <span>class Hostile(object): </span> <span>def attack(self, target): </span> <span># ... </span> <span>class Dog(Animal): </span> <span># ... </span> <span>class Cat(Animal, Hostile): </span> <span># ... </span> dave <span>= Cat(); </span>dave<span>.walk(); </span>dave<span>.attack(target); </span>
多重継承は、ダイヤモンドの問題に苦しんでいます(2つの親クラスが同じ方法を定義する場合)。一部の言語では、ミキシンのような他の戦略を実装することにより、この問題をかわします。 ミックスインは、方法のみを含む小さなクラスです。これらのクラスを拡張する代わりに、ミックスインは別のクラスに含まれています。たとえば、PHPでは、特性を使用してミキシンが実装されています
a Recap:ES2015 Class Syntax<span>interface Hostile { </span> <span>attack(); </span><span>} </span> <span>class Animal { </span> <span>walk(); </span><span>} </span> <span>class Dog extends Animal { </span> <span>// ... </span><span>} </span> <span>class Cat extends Animal implements Hostile { </span> <span>attack() { </span> <span>// ... </span> <span>} </span><span>} </span>
ES2015クラスに飛び込む機会がなかった場合、またはそれらについて十分に知らないと感じた場合は、Jeff Mottのオブジェクト指向のJavaScriptを必ず読んでください。 > 一言で言えば
class foo {...} foo
という名前のクラスについて説明しますclass foo extends bar {...} foo、他のクラスを拡張するクラスについて説明します
- クラスブロック内で、そのクラスのプロパティを定義できます。この記事では、コンストラクターと方法を理解する必要があります。
- constructor(){...}は、作成時に実行される予約された関数です(new foo())
という名前のメソッドを作成します
- クラスの構文は、JavaScriptのプロトタイプモデルよりも主に構文糖です。クラスを作成する代わりに、関数コンストラクターを作成します:
- ここでの要点は、JavaScriptがクラスベースのOOP言語ではないことです。構文は欺cept的であると主張するかもしれません。 ES2015クラスの構成 エラーをスローするダミーメソッドを作成することにより、
前に提案されたように、このアプローチは継承に依存しています。複数のクラスを継承するには、複数の継承またはミキシンが必要になります。
<span>class Animal { </span> <span>// ... </span><span>} </span> <span>trait Hostile { </span> <span>// ... </span><span>} </span> <span>class Dog extends Animal { </span> <span>// ... </span><span>} </span> <span>class Cat extends Animal { </span> <span>use Hostile; </span> <span>// ... </span><span>} </span> <span>class Robot { </span> <span>use Hostile; </span> <span>// ... </span><span>} </span>
別のアプローチは、定義された後にクラスを検証するユーティリティ関数を作成することです。この例は、ちょっと待って、JavaScriptは複数の継承をサポートしています!アンドレア・ジャンマルチによる。セクション「基本的なオブジェクト。実装関数チェック」を参照してください。
複数の継承とミキシンを適用するさまざまな方法を探る時間。以下のすべての検査された戦略は、githubで入手できます。
object.Assign(childclass.prototype、mixin ...)
<span>class Foo {} </span><span>console.log(typeof Foo); // "function" </span>
実証するには、次のコードをご覧ください
これらのプロトタイプオブジェクトは、実行時に作成および変更できます。当初、私は動物と敵対的にクラスを使用しようとしました:
<span>class Animal(object): </span> <span>def walk(self): </span> <span># ... </span> <span>class Hostile(object): </span> <span>def attack(self, target): </span> <span># ... </span> <span>class Dog(Animal): </span> <span># ... </span> <span>class Cat(Animal, Hostile): </span> <span># ... </span> dave <span>= Cat(); </span>dave<span>.walk(); </span>dave<span>.attack(target); </span>
。実際には、これはObject.Assign(...)をクラスからコピーしないことを意味します。これにより、メソッドをあるクラスから別のクラスにコピーする関数を作成することも困難になります。ただし、各メソッドを手動でコピーできます 別の方法は、クラスを捨てて、オブジェクトをミックスインとして使用することです。肯定的な副作用は、ミックスオブジェクトを使用してインスタンスを作成し、誤用を防ぐことができないことです。
<span>interface Hostile { </span> <span>attack(); </span><span>} </span> <span>class Animal { </span> <span>walk(); </span><span>} </span> <span>class Dog extends Animal { </span> <span>// ... </span><span>} </span> <span>class Cat extends Animal implements Hostile { </span> <span>attack() { </span> <span>// ... </span> <span>} </span><span>} </span>
<span>class Animal { </span> <span>// ... </span><span>} </span> <span>trait Hostile { </span> <span>// ... </span><span>} </span> <span>class Dog extends Animal { </span> <span>// ... </span><span>} </span> <span>class Cat extends Animal { </span> <span>use Hostile; </span> <span>// ... </span><span>} </span> <span>class Robot { </span> <span>use Hostile; </span> <span>// ... </span><span>} </span>
- cons
object.Assign()は少しあいまいです
-
ES2015クラスを操作するためのプロトタイプの継承を再発明する
- コンストラクターにオブジェクトを構成する
- ES2015クラスを使用すると、コンストラクター内のオブジェクトを返すことでインスタンスをオーバーライドできます。
- その機能を活用して、サブクラス内の複数のクラスからオブジェクトを作成できます。 Object.Assign(...)はまだミックスクラスではうまく機能しないことに注意してください。そのため、ここでもオブジェクトを使用しました。
これは、上記のコンテキストでのクラス(非記録的な方法を使用)を指すため、Object.Assign(...、これ)は猫の方法をコピーしません。代わりに、Object.Assign()がそれらを適用できるようにするために、これにこれにフィールドとメソッドを明示的に設定する必要があります。
このアプローチは実用的ではありません。インスタンスの代わりに新しいオブジェクトを返すため、基本的に次のように相当します。
<span>class Foo {} </span><span>console.log(typeof Foo); // "function" </span>
pro
<span>class IAnimal { </span> <span>walk() { </span> <span>throw new Error('Not implemented'); </span> <span>} </span><span>} </span> <span>class Dog extends IAnimal { </span> <span>// ... </span><span>} </span> <span>const robbie = new Dog(); </span>robbie<span>.walk(); // Throws an error </span>
動作します、私は推測しますか?
<span>function <span>MyFunction</span> () { </span> <span>this.myOwnProperty = 1; </span><span>} </span><span>MyFunction.prototype.myProtoProperty = 2; </span> <span>const myInstance = new MyFunction(); </span> <span>// logs "1" </span><span>console.log(myInstance.myOwnProperty); </span><span>// logs "2" </span><span>console.log(myInstance.myProtoProperty); </span> <span>// logs "true", because "myOwnProperty" is a property of "myInstance" </span><span>console.log(myInstance.hasOwnProperty('myOwnProperty')); </span><span>// logs "false", because "myProtoProperty" isn’t a property of "myInstance", but "myInstance.__proto__" </span><span>console.log(myInstance.hasOwnProperty('myProtoProperty')); </span>
cons
<span>class Animal { </span> <span>walk() { </span> <span>// ... </span> <span>} </span><span>} </span> <span>class Dog { </span> <span>// ... </span><span>} </span> <span>Object.assign(Dog.prototype, Animal.prototype); </span>
非常にあいまいな
ES2015クラスの構文
からゼロの利点-
ES2015クラスの誤用
このアプローチは、実行時にクラスを定義するJavaScriptの能力を活用しています。
- 最初に、基本クラスが必要になります。私たちの例では、動物とロボットは基本クラスとして機能します。ゼロから始めたい場合は、空のクラスも機能します。
- 次に、パラメーターとして渡されるクラスベースを拡張する新しいクラスを返す工場関数を作成する必要があります。これらは混合物です:
- ここで、敵対的なクラスと関数に渡されたクラスを組み合わせた新しいクラスを返す敵意に任意のクラスを渡すことができます:
複数のクラスをパイプでパイプ化することができます。
オブジェクトを基本クラスとして使用することもできます。pro
すべての情報がクラス宣言ヘッダーにあるため、
<span>Object.assign(Cat.prototype, { </span> <span>attack: Hostile.prototype.attack, </span> <span>walk: Animal.prototype.walk, </span><span>}); </span>
<span>const Animal = { </span> <span>walk() { </span> <span>// ... </span> <span>}, </span><span>}; </span> <span>const Hostile = { </span> <span>attack(target) { </span> <span>// ... </span> <span>}, </span><span>}; </span> <span>class Cat { </span> <span>// ... </span><span>} </span> <span>Object.assign(Cat.prototype, Animal, Hostile); </span>
- 実行時にクラスを作成すると、スタートアップのパフォーマンスやメモリの使用に影響を与える可能性があります
結論
このトピックを調査し、それに関する記事を書くことにしたとき、JavaScriptのプロトタイプモデルがクラスを生成するのに役立つことを期待していました。クラスの構文はメソッドを許可できないため、オブジェクトの操作ははるかに難しくなり、ほとんど非実用的になります。
クラスの構文は、JavaScriptがクラスベースのOOP言語であるという幻想を作成する可能性がありますが、そうではありません。ほとんどのアプローチを使用すると、複数の継承を模倣するためにオブジェクトのプロトタイプを変更する必要があります。クラスの工場関数を使用する最後のアプローチは、ミキシンを使用してクラスを構成するための許容可能な戦略です。プロトタイプベースのプログラミングが制限されていると思う場合は、考え方を見てみたいと思うかもしれません。プロトタイプは、あなたが利用できる比類のない柔軟性を提供します。
何らかの理由で、クラシックプログラミングを依然として好む場合、JavaScriptにコンパイルする言語を調べたい場合があります。たとえば、TypeScriptは、(オプションの)静的タイピングと他の古典的なOOP言語から認識されるパターンを追加するJavaScriptのスーパーセットです。プロジェクトで上記のアプローチのいずれかを使用しますか?より良いアプローチを見つけましたか?コメントでお知らせください!
この記事は、ジェフ・モット、スコット・モリナリ、ビルダン・ソフト、ジョーン・インによって査読されました。 SetePointコンテンツを最高にするためにSitePointのピアレビュアーのすべてに感謝します!JavaScript ES2015オブジェクト継承に関するよくある質問
JavaScriptの古典的継承とプロトタイプの継承の違いは何ですか?JavaやCなどの言語でよく使用される古典的継承は、クラスに基づいています。クラスはオブジェクトの青写真を定義し、オブジェクトはクラスのインスタンスです。継承は、スーパークラスからサブクラスを作成することで達成されます。一方、JavaScriptは、オブジェクトが他のオブジェクトから直接継承するプロトタイプ継承を使用します。これは、オブジェクトを実行時に動的に拡張または変更できるため、より柔軟です。オブジェクトの親に関数を呼び出します。コンストラクターで使用する場合、「スーパー」キーワードが単独で表示され、「この」キーワードが使用される前に使用する必要があります。 「スーパー」キーワードを使用して、メソッド内の親オブジェクトの関数を呼び出すこともできます。
javascriptの「プロトタイプ」とは何ですか?継承でどのように使用されていますか?
JavaScriptでは、すべての関数とオブジェクトには「プロトタイプ」プロパティがあります。このプロパティは、別のオブジェクトであるプロトタイプオブジェクトへの参照です。関数が作成されると、そのプロトタイプオブジェクトは、関数のプロトタイププロパティを介して作成およびリンクされます。コンストラクター関数を使用してオブジェクトを作成すると、コンストラクターのプロトタイプからプロパティとメソッドを継承します。ただし、ミキシンを使用して間接的に達成できます。ミックスインは、あるオブジェクトから別のオブジェクトにプロパティをコピーすることを含む手法です。これにより、オブジェクトは複数のソースからプロパティとメソッドを継承できます。クラス内のオブジェクトを作成および初期化するために使用される特別な方法。継承のコンテキストでは、サブクラスコンストラクターは、「この」キーワードを使用する前に「スーパー」キーワードを使用してスーパークラスコンストラクターを呼び出す必要があります。 >
以上がJavaScript ES2015のオブジェクト継承のパターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。
