ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript プロトタイプ チェーンのメンテナンスと継承_JavaScript スキルの詳細な説明

JavaScript プロトタイプ チェーンのメンテナンスと継承_JavaScript スキルの詳細な説明

WBOY
WBOYオリジナル
2016-05-16 16:30:271426ブラウズ

1 つ。プロトタイプ 2 つ

JavaScript がプロトタイプの継承であることは多くの人が知っています。各コンストラクターにはプロトタイプのメンバーがあり、それを通じて JavaScript の継承を美しく説明できます。 実際、JavaScript の継承は、この属性のみに依存して完了することはできません。
継承を完了するためにコードで使用するプロトタイプについてはここでは説明しません。
を確認してください。 もう一人の目に見えないプロトタイプのメンバー。
各インスタンスには、プロトタイプを指すプロトタイプ属性があります。この属性は、JavaScript の継承を維持するための基礎であるため、アクセスできません。もちろん、変更することもできません。

コードをコピーします コードは次のとおりです:
//コンストラクター宣言
関数 Guoyansi(){ }
関数 GuoyansiEx(){}
//プロトタイプの継承
GuoyansiEx.prototype=new Guoyansi();
// オブジェクトを作成します
var g1=new GuoyansiEx();
var g2=new GuoyansiEx();

上記のコード内のオブジェクトは、次の図で示すことができます

2. プロトタイプのメンテナンス

コンストラクターによって生成されたインスタンスのコンストラクター属性は、常にコンストラクターを指します。これは一時的に正しいと考えられます。

コードをコピーします コードは次のとおりです:
関数 Guoyansi(){ }
var obj1=new Guoyansi();
console.log(obj1.constructor===Guoyansi);//true

実際、コンストラクター自体には属性コンストラクターがありません。では、この属性はどこから来たのでしょうか?

答えは、プロトタイプからです。
したがって、次の結論が得られます

コードをコピー コードは次のとおりです。
obj1.constructor===Guoyansi.prototype.constructor= ==Guoyansi
コンストラクターを介してコンストラクターを見つけることができるため、上記の図をさらに改善できます。

コードをコピーします コードは次のとおりです:
関数 GuoyansiEx(){}
GuoyansiEx.prototype=new Guoyansi();
console.log(GuoyansiEx.constructor===GuoyansiEx)//false

上の図によると、上の結果は true であるはずですが、なぜ false なのでしょうか?


それでは分析を行ってみましょう。

GuoyansiEx のプロトタイプは Guoyansi のインスタンスによって書き換えられたため、GuoyansiEx のプロトタイプ内のコンストラクターは当然 Guoyansi のインスタンスからのものです。
Guoyansi インスタンスのコンストラクターは Guoyansi.prototype から来ており、Guoyansi.prototype は書き換えられていません。
したがって、Guoyansi.prototype のコンストラクターは Guoyansi (コンストラクター) を指します。

上記の分析に基づいて、次の結論が導き出されます

コードをコピーします コードは次のとおりです。
GuoyansiEx.constructor===Guoyansi.constructor===グオヤンシ;
開発プロセス中にコンストラクターの指示が非常に正確である場合は、次のことができます。

コードをコピーします コードは次のとおりです:
/**方法 1:**/
関数 Guoyansi(){}
関数 GuoyansiEx(){}
GuoyansiEx.prototype=new Guoyansi();
guoyansiex.prototype.constructor = guoyansiex; //コンストラクターポインターをリセットします

コードをコピー コードは次のとおりです:

/**
方法 2
**/
関数 Guoyansi(){}
関数 GuoyansiEx(){
This.constructor=arguments.callee;
}
GuoyansiEx.prototype=new Guoyansi();

コードをコピーします コードは次のとおりです:

/**
方法 3
**/
関数 Guoyansi(){}
関数 GuoyansiEx(){
This.constructor=GuoyansiEx;
}
GuoyansiEx.prototype=new Guoyansi();

3. 目に見えないプロトタイプの用途は何ですか?

目に見えるプロトタイプ チェーンを操作して継承を完了することはできますが、この目に見えないプロトタイプ チェーンを表示したり操作したりすることはできません。
オブジェクト指向の継承には、親クラスとの類似性という特性があります。したがって、サブクラスでは親クラスから継承したメンバーを削除することはできません。つまり、サブクラスは親クラスの特性を持たなければなりません。
この機能を維持するために、JavaScript はオブジェクト内に目に見えないプロトタイプ属性を作成し、ユーザーがその属性にアクセスすることを許可しません。このようにして、ユーザーは任意の目的でコンストラクターを変更できます。 サブクラスが持つ親クラスの特性を破壊することはありません。
つまり、内部プロトタイプは JavaScript のプロトタイプ継承メカニズムに必要ですが、外部プロトタイプはユーザーが継承を実装するために必要です。

4. Firefox エンジン SpiderMonkey の __proto__


まだこのコードです。

コードをコピーします コードは次のとおりです:
関数 Guoyansi(){}
Guoyansi.prototype.age=24;
関数 GuoyansiEx(){}
var obj1=new Guoyansi();
GuoyansiEx.prototype=obj1;
GuoyansiEx.prototype.constructor=GuoyansiEx;// コンストラクター ポインターをリセットします。
var obj2=new GuoyansiEx();


今度は、親クラス Guoyansi のプロトタイプの属性の年齢に、obj から上にアクセスしたいと考えています。 アイデアはこれです。

ステップ 1: obj2====>obj2.constructor.prototype
パート 2: obj2.constructor.prototype===>GuoyansiEx.prototype;
パート 3: GuoyansiEx.prototype===>obj1;
パート 4: obj1.constructor====>Guoyansi
パート 5: Guoyansi.prototype.age


次のように記述します: console.log(obj2.constructor.prototype.constructor.prototype.age)//24;

最終結果は 24 です。

最終結果は 24 です。正常に実行できますが、コンストラクターを変更すると親クラスのプロトタイプが見つからなくなると書かれていることが多いです。


Firefox でより簡潔なプロパティが導入されました。_proto_

SpiderMonkey は、デフォルトで、作成されたオブジェクトに _proto_ という名前の属性を追加します。これは、コンストラクターによって使用されるプロトタイプを指します。

実際、これは上で述べた目に見えないプロトタイプチェーンですが、ここでは偽装して公開されているだけです。 このようにして age
にアクセスできます console.log(obj2.__proto__.__proto__.age);//24
これは確かに親クラスのプロトタイプ属性に正常にアクセスしますが、この属性は Firefox にのみ適用され、他のブラウザではエラーが発生します。
E5 では、Object.getPrototypeOf() が Object に拡張され、すべての親クラスのプロトタイプにアクセスできるようになりました。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。