プロトタイプ継承
25939 ワード
📚 Reference
javascript.info, https://ko.javascript.info/prototype-inheritance
注意:これは個人がサイトで復習しやすいように再編成された文章です.
詳細については、リファレンスサイトにアクセスしてください.
プロトタイプ継承
開発中に既存の機能を使用して拡張する必要がある場合があります.
user
という名前のオブジェクトがuser
とかなり似ていると仮定しますが、admin
とguest
を作成する必要があります.「user
メソッドを複製または再実装しなければ、user
にいくつかの機能を追加して、admin
およびguest
オブジェクトを作成することができますよね?」そう思うJavaScript言語の固有機能「プロトタイプ継承」(prototype継承)を利用して、上記のアイデアを実現できます.
[[Prototype]]
JavaScriptのオブジェクトには、リストに
[[Prototype]]
という名前の非表示のpropertyがあります.この非表示のプロパティ値はnull
または他のオブジェクトへの参照です.他のオブジェクトを参照する場合、参照先は「プロトタイプ」と呼ばれます.原型の振る舞いには「神秘的」な面がある.
object
でPropertyを読みたいです.PropertyがなければJavaScriptは自動的にPrototypeでPropertyを検索しますから.プログラミングでは、この動作を「プロトコルタイプ継承」と呼ぶ.多くの便利な機能や開発テクニックは、プロトコルタイプ継承に基づいて作成されています.[[Prototype]]
は内部Propertyであり、非表示Propertyでもあるが、開発者は様々な方法で値を設定することができる.以下の例に示すように、特殊名称
__proto__
を使用して値を設定できます.let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal;
🔥 __proto__
は、[[Prototype]]
用のgetter・setterである.__proto__
と[[Prototype]]
は違います.__proto__
は、[[Prototype]]
のgetter(取得者)およびsetter(設定者)である.互換性が低いため、__proto__
を使用してもよいが、最近作成されたスクリプトでは、関数__proto__
またはObject.getPrototypeOf
を使用してプロトタイプ(Object.setPrototypeOf
)または設定(get
)が得られる.JavaScript宣言では、
set
はブラウザ環境でのみサポートされることが規定されており、実際にはすべてのホスト環境(サーバ側を含む)が__proto__
をサポートしています.オブジェクト
__proto__
からPropertyを取得したいが、Propertyがない場合、JavaScriptはrabbit
という名前のオブジェクトから自動的にPropertyを取得します.let animal = {
eats: true
};
let rabbit = {
jumps: true
};
rabbit.__proto__ = animal; // (*)
// 프로퍼티 eats과 jumps를 rabbit에서도 사용할 수 있게 되었습니다.
alert( rabbit.eats ); // true (**)
alert( rabbit.jumps ); // true
animal
と表記された行では、(*)
がanimal
のプロトタイプに設定されている.rabbit
とマークされた行では、(**)
関数はalert
を読もうとしたが、rabbit.eats
にはrabbit
というpropertyはなかった.JavaScriptは、eats
参照オブジェクト[[Prototype]]
からanimal
を取得する.下から下の図を見てください.「
eats
の原型は現在rabbit
です.」または「animal
はrabbit
を継承します.」そう言ってもいいです.プロトタイプが設定されているので、
animal
においてもrabbit
で実現される有用なプロトタイプや方法を用いることができる.このタイプで継承されるpropertyを「継承property(継承属性)」と呼びます.animal
からanimal
に定義されたメソッドを継承propertyを使用して呼び出す.let animal = {
eats: true,
walk() {
alert("동물이 걷습니다.");
}
};
let rabbit = {
jumps: true,
__proto__: animal
};
// 메서드 walk는 rabbit의 프로토타입인 animal에서 상속받았습니다.
rabbit.walk(); // 동물이 걷습니다.
プロトタイプ(rabbit
)からanimal
が自動的に継承されるので、walk
はrabbit
を呼び出すこともできる.let animal = {
eats: true,
walk() {
alert("동물이 걷습니다.");
}
};
let rabbit = {
jumps: true,
__proto__: animal
};
let longEar = {
earLength: 10,
__proto__: rabbit
};
// 메서드 walk는 프로토타입 체인을 통해 상속받았습니다.
longEar.walk(); // 동물이 걷습니다.
alert(longEar.jumps); // true (rabbit에서 상속받음)
プロトタイプフィルタには3つの制限があります.📌 循環参照は許可されていません(循環参照).
walk
を使用して他のオブジェクトを閉じた形式で参照すると、エラーが発生します.📌 値
__proto__
は、オブジェクトまたは__proto__
のみです.他のデータ型は無視されます.📌 オブジェクトには
null
しかありません.オブジェクトは2つのオブジェクトを継承できません.プロトタイプは読み取り専用です
プロトタイプは、Propertyの読み込み時にのみ使用されます.
基本情報を追加、変更、または消去する操作は、オブジェクトに直接行わなければなりません.
オブジェクト
[[Prototype]]
に直接メソッドrabbit
を割り当てます.let animal = {
eats: true,
walk() {
/* rabbit은 이제 이 메서드를 사용하지 않습니다. */
}
};
let rabbit = {
__proto__: animal
};
rabbit.walk = function() {
alert("토끼가 깡충깡충 뜁니다.");
};
rabbit.walk(); // 토끼가 깡충깡충 뜁니다.
呼び出しwalk
は、プロトタイプのメソッドを実行するのではなく、オブジェクトrabbit.walk()
に直接追加するメソッドを実行する.ただし、アクセス者属性(accessor property)はsetter関数を使用してpropertyに値を割り当てるため、アクセス者属性(
rabbit
)に値を割り当てるとsetter関数が呼び出されると、オブジェクト((**)
)はproperty(admin
)を追加しません.これは上記の例とは少し異なります.let user = {
name: "John",
surname: "Smith",
set fullName(value) {
[this.name, this.surname] = value.split(" ");
},
get fullName() {
return `${this.name} ${this.surname}`;
}
};
let admin = {
__proto__: user,
isAdmin: true
};
alert(admin.fullName); // John Smith (*)
// setter 함수가 실행됩니다!
admin.fullName = "Alice Cooper"; // (**)
alert(admin.fullName); // Alice Cooper, setter에 의해 추가된 admin의 프로퍼티(name, surname)에서 값을 가져옴
alert(user.fullName); // John Smith, 본래 user에 있었던 프로퍼티 값
プロトタイプfullName
にはgetter関数user
が含まれているため、get fullName
とマークされた行には(*)
が呼び出される.同様に、setter関数がプロトコルタイプで定義されているため(get fullName
)、set fullName
でマークされた行で割当て演算が実行されると、オブジェクト(**)
に構成を追加するのではなく、プロトコルタイプのsetter関数が呼び出される.上記の例によれば、「
user
本明細書のset fullName(value)
には、どのような値が含まれていますか?」という疑問があるかもしれません.「property this
およびthis.name
で値が使用される場合、この値はthis.surname
に格納されますか、それともuser
に格納されますか?」という疑問も生まれます.答えは簡単です.
admin
はプロトタイプの影響を受けません.this
は、オブジェクトから呼び出される方法でもプロトタイプから呼び出される方法でも、常にthis
の前に位置する..
でsetter関数が呼び出されると、admin.fullName=
はthis
ではなくuser
である.通常、オブジェクトを作成し、多くの方法を実装してから、これらの大きなオブジェクトに複数のオブジェクトを継承させるため、これらの特性を理解する必要があります.継承メソッドを使用しても、オブジェクトはプロトタイプではなく自身の状態を変更します.
例を通してさらに理解してみましょう.
admin
に「メソッドストレージ」として機能するオブジェクトanimal
を継承させる.呼び出し
rabbit
は、rabbit.sleep()
のパーセントをオブジェクトrabbit
に追加する.// animal엔 다양한 메서드가 있습니다.
let animal = {
walk() {
if (!this.isSleeping) {
alert(`동물이 걸어갑니다.`);
}
},
sleep() {
this.isSleeping = true;
}
};
let rabbit = {
name: "하얀 토끼",
__proto__: animal
};
// rabbit에 새로운 프로퍼티 isSleeping을 추가하고 그 값을 true로 변경합니다.
rabbit.sleep();
alert(rabbit.isSleeping); // true
alert(animal.isSleeping); // undefined (프로토타입에는 isSleeping이라는 프로퍼티가 없습니다.)
上記のコードを実行すると、オブジェクトの状態は次の図のようになります.isSleeping
のほか、rabbit
、bird
などがsnake
を継承している.これらのオブジェクトはまた、animal
の方法、例えばrabbit
を使用してもよい.継承メソッドのanimal
は、実際のメソッドが呼び出されたとき(this
)より前のポイント(animal
)のオブジェクトとなる.したがって、.
にデータを書き込むと、this
ではなくオブジェクトの状態が変化します.これにより,メソッドは共有されているが,オブジェクトの状態は共有されていないと断定できる.
for...複文
animal
はまた、Propertyを継承して巡回オブジェクトに含める.let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
// Object.keys는 객체 자신의 키만 반환합니다.
alert(Object.keys(rabbit)); // jumps
// for..in은 객체 자신의 키와 상속 프로퍼티의 키 모두를 순회합니다.
for(let prop in rabbit) alert(prop); // jumps, eats
for..in
では、継承プロトコルを巡回ターゲットから除外できます.この組み込み方法は、obj.hasOwnProperty(key)
に対応するpropertyがpropertyを継承するのではなく、key
で直接実施されるpropertyである場合にのみobj
に戻る.アプリケーション
true
は、以下の例のように継承propertyをフィルタリングしてもよいし、継承propertyに対してのみいくつかの動作を実行してもよい.let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
for(let prop in rabbit) {
let isOwn = rabbit.hasOwnProperty(prop);
if (isOwn) {
alert(`객체 자신의 프로퍼티: ${prop}`); // 객체 자신의 프로퍼티: jumps
} else {
alert(`상속 프로퍼티: ${prop}`); // 상속 프로퍼티: eats
}
}
上記の例の継承関係は、次の図のようになります.obj.hasOwnProperty(key)
継承rabbit
animal
継承animal
Object.prototype
継承Object.prototype
.null
がanimal
を継承するのは、Object.prototype
がオブジェクト文字で宣言されているためであることに注意してください.図に示すように、
animal
で使用される方法for..in
は、hasOwnProperty
から来ている.うん.しかし継承property
Object.prototype.hasOwnProperty
は複数のウィンドウで出力され、eats
は出力されなかった.いったい何があったのか.原因は簡単です.
hasOwnProperty
は列挙できる(hasOwnProperty
)番組ではないからです.enumerable
のすべての方法のObject.prototype
フラグはenumerable
であり、false
はリスト可能な項目のみを含むため、for..in
は複数のウィンドウに出力されない.🔥 キー-値を巡回するほとんどの方法では、継承プロセスを除外する動作があります.
ほとんどの方法(例えば、
hasOwnProperty
およびObject.keys
)は、オブジェクトのキー値に対して何らかの操作を実行するが、Propertyを継承することは含まれない.「≪プロトコル・タイプ|Protocol Type|oraolap≫」から継承されたプロトコルに加えて、オブジェクトで定義されたプロトコルのみが計算対象に含まれます.
Reference
この問題について(プロトタイプ継承), 我々は、より多くの情報をここで見つけました https://velog.io/@gusdnr814/프로토타입-상속テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol