ホームページ  >  記事  >  ウェブフロントエンド  >  JS プロトタイプ チェーン継承の詳細 ブログ カテゴリ: JavaScript

JS プロトタイプ チェーン継承の詳細 ブログ カテゴリ: JavaScript

巴扎黑
巴扎黑オリジナル
2016-11-25 10:02:541272ブラウズ

1. プロトタイプのみを継承する方法

まず、次のコードを見てください。 }

A.prototype.eat=function(){ console.log("食べられる") }

function B(){}

B.prototype=new A;//B は A を継承します

var cc=new B;

cc.eat();//私は

cc.name;//「Li Keke」を食べることができます

私たちがわかるのは、AがBのすべての属性を継承しているということです。 B に A.prototype 属性のみを継承させ、A には名前や年齢などの無駄なものを多くしたくない場合はどうすればよいでしょうか?

このままで終わってしまうのではないかと思った人もいるかもしれません:

Js code

B.prototype=A.prototype;

var cc=new B;

cc.eat();//

cc.name;//未定義

を食べられますよ、完璧ですね?

Js コード

B.prototype.fuck=function(){console.log("I fun you!")}

var cc=new B,dd=new

cc を見てください。ファック( );// クソだ!

dd.fuck();// クソだ!

// なんてことだ、どうして二人とも呪うことを覚えたのだろう

//サブクラス B の変更は A のプロトタイプにも影響します (もちろんその逆も同様です)。理由は非常に簡単です。A.prototype が B のプロトタイプを指すようにするためです。

関数をビルドし、空のオブジェクトを作成します。空のオブジェクトのプロトタイプが継承される親オブジェクトを指すようにし、最後にオブジェクトのインスタンスを返します。 コードは次のとおりです。

Js コード

Object.createPro=function(pro){

function F(){}

F.prototype =pro;

return new F;

}

テストできます:

Js code

function A(){

this.name="Li Keke ";

this.age=21;

}

A.prototype.eat=function(){ console.log("食べられる") }

function B(){}

B.prototype= Object.createPro(A.prototype);/ /B は A のプロトタイプ属性のみを継承します

var cc=new B;

cc.eat();//

cc.name を食べることができます;//

B.prototype.fuck=function( ){console.log("I got you!")}//B のプロトタイプを変更します

var dd=new A;

dd.fuck();/ /Report TypeError

//Explain B.prototype この変更は A のプロパティには影響しません

しかし、それを行うのは非常に面倒なので、ES5 では、付属の静的メソッド create() を直接使用できます。オブジェクト:

Js コード

function A(){

this.name="Li Keke";

}

A.prototype.eat=function(){ コンソール。 log("食べられる") }

function B(){}

B.prototype=Object.create(A.prototype);// A のプロトタイプのみを継承します

継承中に、いくつかの固有の属性を追加することもできます

Js コード

function A(){

this.name="Li Keke";

}

A.prototype.eat=function(){ console.log("食べられる") }

function B(){}

B.prototype=Object.create(A.prototype,{

p: { 値: 42、書き込み可能: false、列挙可能: true }//属性 p を追加します。これは書き込み可能ではありませんが、列挙可能です

});

var pp=new B;

pp.p;//42

pp.name;//未定義

pp。 Eat(); // 食べられます

pp.p=666;

pp.p;//42 (書き込み不可)

2 番目のパラメーターは、複数のプロパティを設定できる Object.defineproperties() とよく似ています。そして、特別な許可タグを付与します

もちろん、次の

Js コード

B.prototype=Object.create(new A); のように、このメソッドを通じて A のすべての属性を継承することもできます。 Object.create メソッドの互換性、ES5 と互換性のあるブラウザのみが可能であること、または上記の Object.createPro メソッドと同様に、自分でシミュレートすることもできます

2. コンストラクターのポインティングとコンストラクターの列挙可能性の問題について

最初の質問では、異なるクラス間の継承を実装するために Object.create メソッドを使用しましたが、これを実行すると、次のように問題が発生します。 "リ・ケケ";

this.age=21;

}

A.prototype.eat=function(){ console.log("食べられる") }

function B(){}

B .prototype=Object.create(A.prototype);

var cc=new B;

cc.constructor;//A (ここでは値がBであると予想していましたが、実際にはAになりました)

上記の問題を解決するにはどうすればよいでしょうか?

Js コード

//考えられる最も簡単な方法は、次のようにコンストラクター属性を手動で設定することです

B.prototype.constructor=B;

次に、問題が再び発生します。以下を参照してください。 code

B.prototype.propertyIsEnumerable("constructor");//true (設定したコンストラクター プロパティは列挙可能です)

もちろん、このようなことは望ましくないので、どうすればよいでしょうか?

Js コード

//Object.defineProperty または Object.defineProperties メソッドを使用して、コンストラクターの列挙可能値を false に設定します

Object.defineProperty(B.prototype,"constructor",{

value:B,

) enumerable:false/ /Non-enumerable

});

cc.constructor;//B

B.prototype.propertyIsEnumerable("constructor");//false

同様の問題を抱えている人の中には、オブジェクト リテラルを使用してオーバーライドクラス プロトタイプを使用する場合、次のようになります

Js コード

function C(){}

C.prototype={}

var pp=new C;//Object (What C)

C.prototype.constructor=C;

C.prototype.propertyIsEnumerable("constructor");//true (列挙可能)

//上記のメソッドはここでも使用できます

もちろん、書き直す必要がなく、次のように属性を追加するだけの別の方法もあります。

Js code

function D(){}

D.prototype.x=1; gg=new D;

gg.constructor; //D

D.prototype.propertyIsEnumerable("constructor");//false

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