[Avascript]ClassとPrototype
13323 ワード
まず、JavaScriptでClassとPrototypeを紹介する前に、いくつかの重要な事実を理解しておきましょう.
実際,文法的にはJavaScriptにはクラスが存在するが,実際にはクラスは存在しない.
どういう意味か知るためにまずClassを知っておく
クラスとは、通常、オブジェクト向けプログラミングでオブジェクトを印刷するフレームワークを指す.
ECMAScript 2015はいくつかのキーワードを導入し、同時にClassも導入した.
しかし,このとき導入されるクラスは,既存のオブジェクト向けプログラミング言語におけるクラスとは異なる動作方式を持つ.実際、JavaScriptでは、クラスはPrototypeに基づいており、他の言語のクラスとは異なります.
次の例は、JavaScriptでClassを使用する例です.
次のコードに変換して実行すると、値が返されず、オブジェクトがどのように作成されたかが疑われる可能性があります.
JavaScriptでは、関数がnew演算子に遭遇すると不思議な現象が発生します.まず、メモリに新しい空のオブジェクトを作成します.次に、空のオブジェクトを関数のthisにバインドし、オブジェクトのプロパティを塗りつぶす操作を実行します.最後に、関数にreturnが存在しない場合はthisを返します.
次に、クラスの継承を見てみましょう.
しかし、JavaScriptはこのように継承されません.
JavaScriptでは元の値とオブジェクトの参照値しかコピーできないため、親のコンテンツは子のコンテンツにコピーできません.
したがって、Javascriptでは、クラスやオブジェクトのコンテンツをコピーすることなくPrototypeを使用して継承を実現します.
Prototypeは、JavaScriptで継承を実現する方法で、他の言語のようにコンテンツをコピーすることによって継承するのではなく、オブジェクトとオブジェクト間の接続という特性を使用します.
次の画像は、ブラウザコンソールの画面に表示されるプロトタイプです.
特定のオブジェクトに直接アクセスしないプロトタイプオブジェクトの正式な方法-Javascript言語標準仕様では、「リンク」は内部属性によって定義され、「プロトタイプ」として表されるプロトタイプオブジェクトです.(ECMAScriptを参照).しかし、多くの現代ブラウザでは、
継承は
オブジェクトに関連付けられたリンクは、大きく分けて3つに分類されます.
まず、オブジェクトが他のオブジェクトに基づいて作成された場合、オブジェクトはそのプロトタイプへの
オブジェクトが最後にnew+関数によって作成された場合、作成されたオブジェクトの
このとき、プロトタイプフィルタということが起こります.
byooオブジェクトからsayJS関数を呼び出すと、まずbyooオブジェクトにsayJS関数があるかどうかをチェックします.sayJS関数はbyooオブジェクトには存在しませんが、終了しません.
プロトタイプ充填はprototypeを介して行われ、
JavaScriptはプロトタイプベースの言語です.Prototypeを使用してオブジェクト間の継承関係を表し、コピーハンドルではなくPrototypeチェーンを使用して、他の言語で使用されている継承に関連するオブジェクトを検索します.
では、コードを修正して、次のように修正するとどうなりますか?
まず、最初の状況を見てみましょう.
通常、sayJS関数が読み取り専用でない場合.
同じ名前の関数をアトリビュートに追加すると、既存の関数は使用できません.Javascriptではこのようなメソッドオーバーライドは存在しませんが、マスクを使用すると同様の操作が可能になります.
実際,文法的にはJavaScriptにはクラスが存在するが,実際にはクラスは存在しない.
どういう意味か知るためにまずClassを知っておく
Class
クラスとは、通常、オブジェクト向けプログラミングでオブジェクトを印刷するフレームワークを指す.
ECMAScript 2015はいくつかのキーワードを導入し、同時にClassも導入した.
しかし,このとき導入されるクラスは,既存のオブジェクト向けプログラミング言語におけるクラスとは異なる動作方式を持つ.実際、JavaScriptでは、クラスはPrototypeに基づいており、他の言語のクラスとは異なります.
次の例は、JavaScriptでClassを使用する例です.
'use strict'
class Cadet {
constructor(intraID) {
this.intraID = intraID;
}
}
このコードは文法的にはこのように書かれていますが、実際にはfunction Cadet(intraID) {
this.intraID = intraID;
}
こんなコードになる次のコードに変換して実行すると、値が返されず、オブジェクトがどのように作成されたかが疑われる可能性があります.
JavaScriptでは、関数がnew演算子に遭遇すると不思議な現象が発生します.まず、メモリに新しい空のオブジェクトを作成します.次に、空のオブジェクトを関数のthisにバインドし、オブジェクトのプロパティを塗りつぶす操作を実行します.最後に、関数にreturnが存在しない場合はthisを返します.
次に、クラスの継承を見てみましょう.
'use strict'
class Cadet {
constructor(intraID) {
this.intraID = intraID;
}
}
class CadetStduyingJS extends Cadet{ // Cadet을 상속하는 CadetStduyingJS클래스
constructor(intraID) {
super(intraID);
}
doStudy() {
console.log("i'm studying JS);
}
}
典型的なオブジェクト向けプログラミングでは、継承は親クラスの内容を子クラスにコピーして継承します.しかし、JavaScriptはこのように継承されません.
JavaScriptでは元の値とオブジェクトの参照値しかコピーできないため、親のコンテンツは子のコンテンツにコピーできません.
したがって、Javascriptでは、クラスやオブジェクトのコンテンツをコピーすることなくPrototypeを使用して継承を実現します.
Prototype
Prototypeは、JavaScriptで継承を実現する方法で、他の言語のようにコンテンツをコピーすることによって継承するのではなく、オブジェクトとオブジェクト間の接続という特性を使用します.
次の画像は、ブラウザコンソールの画面に表示されるプロトタイプです.
特定のオブジェクトに直接アクセスしないプロトタイプオブジェクトの正式な方法-Javascript言語標準仕様では、「リンク」は内部属性によって定義され、「プロトタイプ」として表されるプロトタイプオブジェクトです.(ECMAScriptを参照).しかし、多くの現代ブラウザでは、
__proto__
(en-US)(前後各2つの下欄)属性を介して特定のオブジェクトにアクセスするプロトタイプオブジェクトが実現されている.たとえば、チェーンがperson1.__proto__
またはperson1.__proto__.__proto__
のコードから構成されていることを確認してください.MDN - ProtoType 継承は
__proto__
という属性を使用して実現され、リンクはオブジェクトとオブジェクトのリンクである.オブジェクトに関連付けられたリンクは、大きく分けて3つに分類されます.
まず、オブジェクトが他のオブジェクトに基づいて作成された場合、オブジェクトはそのプロトタイプへの
__proto__
リンクを自動的に有します.const newObj = Object.create(oldObj)
newObj.__proto__ === oldObj
次のオブジェクトがオブジェクトではなく関数オブジェクトの場合、__proto__
ではなく関数の他のプロトタイプオブジェクトが作成されます.関数のprototypeプロパティは、作成されたprototypeオブジェクトを指し、prototypeオブジェクトはconstructorプロパティを介して関数のループ参照関係を指します.オブジェクトが最後にnew+関数によって作成された場合、作成されたオブジェクトの
__proto__
リンクは、その関数のプロトタイプオブジェクトを指します.function sayJS() {
console.log(`${this.intraID} saying JS!`);
}
function Cadet(intraID) {
this.intraID = intraID;
}
Cadet.prototype.sayJS = sayJS;
const byoo = new Cadet('byoo');
byoo.sayJS();
では、次のコードで、最後のbyooオブジェクトがsayJS関数を呼び出すと、何が起こるのでしょうか.このとき、プロトタイプフィルタということが起こります.
__proto__
リンクを使用してプロトコルタイプを参照すると、プロトコルタイプフィルタが発生します.byooオブジェクトからsayJS関数を呼び出すと、まずbyooオブジェクトにsayJS関数があるかどうかをチェックします.sayJS関数はbyooオブジェクトには存在しませんが、終了しません.
__proto__
リンクでbyooオブジェクトのCate関数を作成したPrototypeオブジェクトに移動し、sayJS関数を検索します.この場合、sayJS関数があるため、sayJS関数がアクティブになります.プロトタイプ充填はprototypeを介して行われ、
__proto__
の値を持つオブジェクト(元のオブジェクト)が現れるとプロトタイプチェーンは停止します.JavaScriptはプロトタイプベースの言語です.Prototypeを使用してオブジェクト間の継承関係を表し、コピーハンドルではなくPrototypeチェーンを使用して、他の言語で使用されている継承に関連するオブジェクトを検索します.
では、コードを修正して、次のように修正するとどうなりますか?
function sayJS() {
console.log(`${this.intraID} saying JS!`);
}
function Cadet(intraID) {
this.intraID = intraID;
}
Cadet.prototype.sayJS = sayJS;
const byoo = new Cadet('byoo');
byoo.sayJS = function(){
console.log('byoo saying JS!');
}
byoo.sayJS();
このコードは、場合によっては異なる操作を実行します.まず、最初の状況を見てみましょう.
Object.defineProperty(Cadet.prototpye, "sayJS", {
writable: false
...
})
Cateプロトタイプオブジェクトに追加されたsayJS関数が読み取り専用の場合、厳格モードではエラーが発生しますが、非厳格モードでは何も起こりません.通常、sayJS関数が読み取り専用でない場合.
Object.defineProperty(Cadet.prototpye, "sayJS", {
writable: true
...
})
属性としてsayJS関数をbyooオブジェクトに追加します.したがって、byooオブジェクトは、既存のプロトコルタイプフィルタによって使用されるsayJS関数にアクセスする方法を失うことになります.同じ名前の関数をアトリビュートに追加すると、既存の関数は使用できません.Javascriptではこのようなメソッドオーバーライドは存在しませんが、マスクを使用すると同様の操作が可能になります.
Reference
この問題について([Avascript]ClassとPrototype), 我々は、より多くの情報をここで見つけました https://velog.io/@ybw903/JavascriptClass와-Prototypeテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol