JavaScriptの各オブジェクトには、プロパティプロトタイプが組み込まれています。 JavaScriptのオブジェクトのプロトタイププロパティの説明は、オブジェクト型プロトタイプへの参照を返すことです。これは、プロトタイプ属性が、現在のオブジェクトの親として機能する別のJavaScriptオブジェクトへの参照を保持することを意味します。
コードコピーは次のとおりです。
A.Prototype = new B();
プロトタイプを理解することは、相続と混同されるべきではありません。 Aのプロトタイプは、Bのインスタンスです。Aは、Bのすべての方法と特性をクローン化したことを理解できます。AはBの方法と特性を使用できます。ここで強調されているのは、相続ではなくクローニングです。これが起こる可能性があります:AのプロトタイプはBのインスタンスであり、BのプロトタイプはAのインスタンスでもあります。
以下の分析を引き続き見てみましょう。
プライベート変数と機能
関数内で定義されている変数と関数が外部から提供されていない場合、外部からアクセスすることはできません。つまり、関数の私的変数と関数です。
コードコピーは次のとおりです。
<script type = "text/javascript">
functionbox(){
var color = "blue"; // private変数
var fn = function()// private function
{
}
}
</script>
このようにして、変数の色とFNには関数オブジェクトボックスの外側にアクセスできず、プライベートになります。
コードコピーは次のとおりです。
var obj = new Box();
アラート(obj.color); //未定義のポップアップ
アラート(obj.fn); //上記と同じ
静的変数と関数
関数が定義されると、追加された属性と関数はオブジェクト自体を介してまだアクセスできますが、それらの例にアクセスすることはできません。このような変数と関数は、それぞれ静的変数と静的関数と呼ばれます。
コードコピーは次のとおりです。
<script type = "text/javascript">
関数obj(){};
obj.num = 72; //静的変数
obj.fn = function()// static function
{
}
アラート(obj.num); // 72
アラート(typeof obj.fn)//関数
var t = new obj();
アラート(T.Name); //未定義
アラート(typeof t.fn); //未定義
</script>
インスタンス変数と関数
オブジェクト指向のプログラミングでは、一部のライブラリ機能に加えて、オブジェクト定義の場合に同時にいくつかのプロパティとメソッドを定義し、インスタンス化後にアクセスできるようにし、JSもこれを行うことができます。
コードコピーは次のとおりです。
<script type = "text/javascript">
functionbox(){
this.a = []; //インスタンス変数
this.fn = function(){// instance method
}
}
console.log(typeof box.a); //未定義
console.log(typeof box.fn); //未定義
var box = new Box();
console.log(typeof box.a); //物体
console.log(typeof box.fn); //関数
</script>
変数とメソッドにインスタンスに新しいメソッドとプロパティを追加する
コードコピーは次のとおりです。
<script type = "text/javascript">
functionbox(){
this.a = []; //インスタンス変数
this.fn = function(){// instance method
}
}
var box1 = new Box();
box1.a.push(1);
box1.fn = {};
console.log(box1.a); // [1]
console.log(typeof box1.fn); //物体
var box2 = new Box();
console.log(box2.a); // []
console.log(typeof box2.fn); //関数
</script>
AとFNはBox1で変更されましたが、Box2では変更されていませんでした。配列と関数はオブジェクトであり、参照タイプであるため、これは、Box1のプロパティとメソッドはBox2のプロパティと同じですが、参照ではなく、Boxオブジェクトによって定義されたプロパティとメソッドのコピーであることを意味します。
これはプロパティに問題はありませんが、メソッドはまったく同じ機能を実行しているため、メソッドにとって大きな問題ですが、2つのコピーがあります。関数オブジェクトに数千のインスタンスメソッドがある場合、その各インスタンスは数千のメソッドのコピーを維持する必要があります。これは明らかに科学的です。私に何ができる?プロトタイプが生まれました。
基本概念
作成する各関数には、オブジェクトへのポインターであるプロトタイププロパティがあり、その目的は、特定のタイプのすべてのインスタンスで共有できるプロパティと方法を含めることです。次に、プロトタイプは、コンストラクターを呼び出すことによって作成されたオブジェクトインスタンスのプロトタイプオブジェクトです。
プロトタイプを使用する利点は、オブジェクトインスタンスが含まれるプロパティとメソッドを共有できることです。つまり、定義オブジェクト情報をコンストラクターに追加する代わりに、この情報をプロトタイプに直接追加できます。コンストラクターを使用することの主な問題は、各インスタンスで各方法を1回作成する必要があることです。
JavaScriptには、元の値とオブジェクト値の2種類の値があります。各オブジェクトには内部プロパティプロトタイプがあり、通常はプロトタイプと呼ばれます。プロトタイプの値は、オブジェクトまたはnullにすることができます。その値がオブジェクトである場合、オブジェクトには独自のプロトタイプも必要です。これは、プロトタイプチェーンと呼ばれる線形チェーンを形成します。
意味
関数はコンストラクターとして使用できます。さらに、関数のみがプロトタイプ属性を持ち、アクセスできますが、オブジェクトインスタンスにはこの属性がありません。内部はアクセスできない__Proto__属性のみがあります。 __Proto__は、関連するプロトタイプへのオブジェクトの神秘的なリンクです。標準によれば、__Proto__は一般に公開されていません。つまり、私有地であることを意味しますが、Firefoxのエンジンがそれを露出し、アクセスして設定できる共通の財産になりました。
コードコピーは次のとおりです。
<script type = "text/javascript">
var browser = function(){};
browser.prototype.run = function(){
アラート(「私はヤモリ、firefoxの核です」);
}
var bro = new browser();
bro.run();
</script>
Bro.run()メソッドを呼び出すと、Broにはそのような方法がないため、彼は__Proto__、つまりbrowser.prototypeでそれを検索するため、run()メソッドが最終的に実行されます。 (ここで、関数の大文字は、通常の機能を区別するためのコンストラクターを表します)
コンストラクターを呼び出してインスタンスを作成すると、インスタンスには、コンストラクターのプロトタイプを指す内部ポインター(__Proto__)が含まれます。この接続は、インスタンスとコンストラクターのプロトタイプの間で、インスタンスとコンストラクターの間ではありません。
コードコピーは次のとおりです。
<script type = "text/javascript">
function person(name){//コンストラクター関数
this.name = name;
}
person.prototype.printname = function()//プロトタイプオブジェクト
{
アラート(this.name);
}
var person1 = new person( 'byron'); //オブジェクトをインスタンス化します
console.log(person1 .__ proto __); // person
console.log(person1.constructor); //自分で試してみてください
console.log(person.prototype); //プロトタイプオブジェクトの人を指します
var person2 = new person( 'frank');
</script>
Person's Instance Person1には名前属性が含まれており、個人のプロトタイプを指す__Proto__属性を自動的に生成し、プロトタイプで定義されている印刷メソッドにアクセスできます。これはおそらく次のようです。
各JavaScript関数には、プロトタイプオブジェクトであるオブジェクトを指すプロトタイプ属性があります。プロトタイプオブジェクトは初期化時に空です。その中のプロパティとメソッドをカスタマイズできます。これらのメソッドとプロパティは、コンストラクターによって作成されたオブジェクトによって継承されます。
それで、今問題はそうです。コンストラクター、インスタンス、プロトタイプオブジェクトの関係は何ですか?
コンストラクター、インスタンス、プロトタイプオブジェクトの違い
インスタンスはコンストラクターを介して作成されます。インスタンスが作成されると、コンストラクター属性(コンストラクター関数を指す)と__Proto__属性(プロトタイプオブジェクトを指す)があります。
コンストラクターにはプロトタイプのプロパティがあります。これは、そのプロトタイプオブジェクトへのポインターです。
また、コンストラクターを指すプロトタイプオブジェクト内にポインター(コンストラクタープロパティ)もあります。
インスタンスは、プロトタイプオブジェクトで定義されているプロパティとメソッドにアクセスできます。
ここでは、person1とperson2はインスタンスであり、プロトタイプはプロトタイプオブジェクトです。
別の栗:
コードコピーは次のとおりです。
<script type = "text/javascript">
function animal(name)//蓄積コンストラクター
{
this.name = name; //オブジェクトプロパティを設定します
}
Animal.prototype.behavior = function()//基本クラスコンストラクターのプロトタイプに動作方法を追加する
{
alert( "これは"+this.name);
}
var dog = new Animal( "dog"); //犬のオブジェクトを作成します
var cat = new Animal( "cat"); // catオブジェクトを作成します
dog.behavior(); //犬のオブジェクトを介して行動方法を直接呼び出します
cat.behavior(); // output "これは猫です"
alert(dog.behavior == cat.behavior); // output true;
</script>
コンストラクターのプロトタイプで定義されている方法が実際にオブジェクトを介して直接呼び出され、コードが共有されることを実行している結果を実行しているプログラムから見ることができます。 (Animal.prototype.behaviorのプロトタイププロパティを削除して、それがまだ実行できるかどうかを確認することができます。)ここで、プロトタイププロパティは動物オブジェクトを指します。
配列オブジェクトインスタンス
配列オブジェクトのインスタンスを見てみましょう。オブジェクトArray1を作成すると、JavaScriptエンジンのArray1の実際のオブジェクトモデルは次のとおりです。
コードコピーは次のとおりです。
var array1 = [1,2,3];
Array1オブジェクトの長さ属性値は3ですが、次の方法でArray1に要素を追加できます。
コードコピーは次のとおりです。
array1.push(4);
プッシュメソッドは、array1(array.prototye.push())の__proto__メンバーによってオブジェクトを指すメソッドに由来します。これはまさに、すべての配列オブジェクト([]を介して作成された)が、プッシュ、リバースなどの同じメソッドオブジェクトを指す__Proto__メンバー(Array.Prototype)を含むため、これらの配列オブジェクトがプッシュ、リバース、およびその他の方法を使用できることです。
関数オブジェクトインスタンス
コードコピーは次のとおりです。
関数base(){
this.id = "base"
}
コードコピーは次のとおりです。
var obj = new base();
そのようなコードの結果は何ですか? JavaScriptエンジンに表示されるオブジェクトモデルは次のとおりです。
新しいオペレーターは正確に何をしましたか?実際、それは非常に単純で、3つのことをしました。
コードコピーは次のとおりです。
var obj = {};
obj .__ proto__ = base.prototype;
base.call(obj);
プロトタイプチェーン
プロトタイプチェーン:オブジェクトからプロパティまたはメソッドが取得された場合、オブジェクト自体にそのようなプロパティまたはメソッドがない場合、関連するプロトタイプオブジェクトを検索します。プロトタイプがない場合、プロトタイプに関連付けられたプロトタイプの前身を検索します。これ以上ない場合は、プロトタイプ.prototypeなどで参照されるオブジェクトを検索し続けます。プロトタイプまで.......プロトタイプが未定義になるまで(オブジェクトのプロトタイプは未定義です)、したがって、いわゆる「プロトタイプチェーン」を形成します。
コードコピーは次のとおりです。
<script type = "text/javascript">
function shape(){
this.name = "shape";
this.toString = function(){
this.nameを返します。
}
}
function twoshape(){
this.name = "2 shape";
}
関数三角形(側、高さ){
this.name = "triangle";
this.side = side;
this.height = height;
this.getarea = function(){
this.side*this.height/2を返します。
}
}
twoshape.prototype = new Shape();
triangle.prototype = new Twoshape();
</script>
ここでは、Constructor Shape()で新しいエンティティが作成され、オブジェクトのプロトタイプを上書きするために使用されます。
コードコピーは次のとおりです。
<script type = "text/javascript">
function shape(){
this.name = "shape";
this.toString = function(){
this.nameを返します。
}
}
function twoshape(){
this.name = "2 shape";
}
関数三角形(側、高さ){
this.name = "triangle";
this.side = side;
this.height = height;
this.getarea = function(){
this.side*this.height/2を返します。
}
}
twoshape.prototype = new Shape();
triangle.prototype = new Twoshape();
twoshape.prototype.constructor = twoshape;
triangle.prototype.constructor = triangle;
var my = new Triangle(5,10);
my.getarea();
my.toString(); //三角形
my.constructor; //三角形(側、高さ)
</script>
プロトタイプの継承
プロトタイプの継承:プロトタイプチェーンの最後に、それはオブジェクトコンストラクタープロトタイプ属性によって指摘されたプロトタイプオブジェクトです。このプロトタイプオブジェクトはすべてのオブジェクトの祖先であり、この祖先は、ToStringなどのすべてのオブジェクトが生まれる必要がある方法を実装しました。関数、ブール、弦、日付、regexpなどの他の組み込みコンストラクターはこの祖先から継承されますが、それぞれ独自の属性と方法を定義しているため、子孫がそれぞれの氏族の特性を示します。
ECMAScriptでは、継承を実装する方法は、プロトタイプチェーンに依存することによって達成されます。
コードコピーは次のとおりです。
<script type = "text/javascript">
function box(){//継承された関数はsupertype(親クラス、ベースクラス)と呼ばれます
this.name = "jack";
}
function tree(){//継承された関数はサブタイプ(サブクラス、派生クラス)と呼ばれます
this.age = 300;
}
//プロトタイプチェーンを介して、サブタイプのプロトタイプ属性を割り当てます
// new Box()は、ボックスコンストラクトの情報とプロトタイプの情報をツリーに引き渡します
tree.prototype = new Box(); //ツリーはボックスを継承し、プロトタイプを介してチェーンを形成します。
var tree = new Tree();
Alert(tree.name); // Popt Jack
</script>
プロトタイプチェーンの問題:プロトタイプチェーンは非常に強力であり、継承を実装するために使用できますが、いくつかの問題もあります。最も重要な問題は、参照タイプを含む値プロトタイプから発生します。参照タイプを含むプロトタイプ属性は、すべてのインスタンスで共有されます。これが、プロトタイプオブジェクトではなく、コンストラクターで属性が定義される理由です。プロトタイプを通じて継承が達成されると、プロトタイプは実際に別のタイプのインスタンスになります。したがって、元のインスタンス属性がプロトタイプ属性になります。
サブタイプのインスタンスを作成する場合、引数をSuperTypeコンストラクターに渡すことはできません。実際、すべてのオブジェクトインスタンスに影響を与えることなく、パラメーターをSuperTypeコンストラクターに渡す方法はないと言われるべきです。プロトタイプに参照型値を含めたために議論されたばかりの問題に加えて、実際にプロトタイプチェーンだけを使用することはまれです。
別の栗:
コードコピーは次のとおりです。
<script type = "text/javascript">
関数担当者(名前)
{
this.name = name; //オブジェクトプロパティを設定します
};
person.prototype.company = "microsoft"; //プロトタイプのプロパティを設定します
person.prototype.sayhello = function()//プロトタイプメソッド
{
alert( "hello、im"+ this.name+ "of"+ this.company);
};
Var Billgates = new Person( "Billgates"); //人オブジェクトを作成します
billgates.sayhello(); //プロトタイプと出力の内容を継承し、「こんにちは、マイクロソフトのビルゲート」
var jobs = new person( "jobs");
jobs.company = "apple"; //自分の会社属性を設定して、プロトタイプの会社属性をカバーする
jobs.sayhello = function()
{
alert( "hi、" + this.name + "like" + this.company);
};
jobs.sayhello(); //あなたが自分自身を上書きするプロパティと方法、出力「こんにちは、Appleのようなジョブ」
billgates.sayhello(); //ジョブのカバレッジはプロトタイプに影響を与えません、ビルゲートはまだ出力します
</script>
プロトタイプチェーンの次の例を参照してください。
コードコピーは次のとおりです。
<script type = "text/javascript">
function year(){
this.value = 21;
}
year.prototype = {
方法:function(){
}
};
function hi(){
};
//年のインスタンスオブジェクトにHIのプロトタイププロパティを設定します
hi.prototype = new Year();
hi.prototype.year = 'hello world';
hi.prototype.constructor = hi;
var test = new hi(); // hiの新しいインスタンスを作成します
//プロトタイプチェーン
テスト[こんにちは例]
hi.prototype [年の例]
{year: 'hello world'}
year.prototype
{方法:…};
object.prototype
{toString:...};
</script>
上記の例から、テストオブジェクトはhi.prototypeおよびyear.prototypeから継承されます。したがって、年間のプロトタイプメソッドメソッドにアクセスでき、同時にインスタンスプロパティ値にアクセスできます
__ptoto__属性
__ptoto__属性(IEブラウザーによってサポートされていない)は、インスタンスのプロトタイプオブジェクトへのポインターです。その機能は、コンストラクターのプロトタイプ属性コンストラクターを指すことです。これらの2つの属性を通じて、プロトタイプのプロパティとメソッドにアクセスできます。
JavaScriptのオブジェクトインスタンスは、本質的に一連のプロパティで構成されています。これらのプロパティの中には、内部的には見えない特別なプロパティがあります - __Proto__。このプロパティの値は、オブジェクトインスタンスのプロトタイプを指します。オブジェクトインスタンスには、一意のプロトタイプのみがあります。
コードコピーは次のとおりです。
<script type = "text/javascript">
function box(){//コンストラクターを表す大文字
box.prototype.name = "trigkit4"; //プロトタイプ属性
box.prototype.age = "21";
box.prototype.run = function()//プロトタイプメソッド
{
this.name + this.age + 'Studying'を返します。
}
}
var box1 = new Box();
var box2 = new Box();
alert(box1.constructor); //属性を作成すると、コンストラクター自体を取得できます。
//関数はプロトタイプポインターによって配置され、コンストラクター自体を取得することになります
</script>
__Proto__属性とプロトタイプ属性の違い
プロトタイプは、関数オブジェクトの独自のプロパティです。
__Proto__は、通常のオブジェクトの暗黙のプロパティです。新規の場合、プロトタイプで指摘されたオブジェクトを指します。
__ptoto__は実際には特定のエンティティオブジェクトの属性であり、プロトタイプはコンストラクターに属する属性です。 __ptoto__は、環境の学習またはデバッグにのみ使用できます。
プロトタイプモードの実行プロセス
1.最初にコンストラクターインスタンスの属性またはメソッドを探します。もしそうなら、すぐに戻ります。
2.コンストラクターのインスタンスがない場合は、そのプロトタイプオブジェクトに移動してすぐに戻ります。
プロトタイプオブジェクト
コードコピーは次のとおりです。
<script type = "text/javascript">
function box(){//コンストラクターを表す大文字
box.prototype.name = "trigkit4"; //プロトタイプ属性
box.prototype.age = "21";
box.prototype.run = function()//プロトタイプメソッド
{
this.name + this.age + 'Studying'を返します。
}
}
var box1 = new Box();
alert(box1.name); // trigkit4、プロトタイプの値
box1.name = "lee";
alert(box1.name); // lee、原則に進みます
var box2 = new Box();
alert(box2.name); // trigkit4、box1で変更されていないプロトタイプの値、
</script>
コンストラクター
コードコピーは次のとおりです。
<script type = "text/javascript">
functionbox(){
this.name = "bill";
}
box.prototype.name = "trigkit4"; //プロトタイプ属性
box.prototype.age = "21";
box.prototype.run = function()//プロトタイプメソッド
{
this.name + this.age + 'Studying'を返します。
}
var box1 = new Box();
alert(box1.name); // bill、プロトタイプの値
box1.name = "lee";
alert(box1.name); // lee、原則に進みます
</script>
要約するには、整理しましょう。
コードコピーは次のとおりです。
<script type = "text/javascript">
function person(){};
person.prototype.name = "trigkit4";
person.prototype.say = function(){
アラート( "hi");
}
var p1 = new person(); //プロトタイプはP1とP2のプロトタイプオブジェクトです
var p2 = new person(); // p2はインスタンス化されたオブジェクトであり、その中に__proto__属性があり、人のプロトタイプを指しています
console.log(p1.prototype); //未定義、このプロパティはオブジェクトであり、アクセスできません
console.log(person.prototype); // person
console.log(person.prototype.constructor); //コンストラクター関数を指すプロトタイプオブジェクト内にポインター(コンストラクタープロパティ)もあります
console.log(p1 .__ proto __); //このプロパティは、プロトタイプのプロトタイプオブジェクトを指すポインターです
p1.say(); //インスタンスは、プロトタイプオブジェクトで定義されているプロパティとメソッドにアクセスできます
</script>
工場モデル
コードコピーは次のとおりです。
関数CreateObject(name、age){
var obj = new object();
obj.name = name;
obj.age = age;
OBJを返します。
}
工場のパターンは、インスタンス化されたオブジェクトの大規模な複製の問題を解決しますが、別の問題があります。つまり、オブジェクトのどのインスタンスを把握することは不可能です。
コンストラクターメソッドを使用すると、繰り返しインスタンス化の問題を解決するだけでなく、オブジェクト認識の問題も解決します。
コンストラクターの方法と工場パターンの使用の違いは次のとおりです。
1。コンストラクターメソッドによって表示されないオブジェクト(新しいオブジェクト())を作成します。
2。このオブジェクトに属性とメソッドを直接割り当てます
3.戻り声明はありません
コンストラクターが使用され、新しいコンストラクター()が使用されると、新しいオブジェクト()がバックグラウンドで実行されます。
関数本文のこれは、新しいオブジェクト()から派生したオブジェクトを表します
1.プロパティがコンストラクターインスタンスにあるのか、プロトタイプにあるかを判断するには、 `hasownProperty()`関数を使用できます。
2。リテラルを作成する方法は、コンストラクター属性を作成するために使用されます。インスタンスはオブジェクトではなく、オブジェクトを指し、コンストラクターを作成する方法は逆です。
なぜ反対を指すのですか? box.prototype = {};この書き方は、実際に新しいオブジェクトを作成することだからです。
関数が作成されるたびに、そのプロトタイプが同時に作成され、このオブジェクトはコンストラクター属性を自動的に取得します
3.インスタンスメソッド、異なるインスタンス化の場合、メソッドアドレスは異なり、一意です。
4.プロトタイプメソッドの場合、アドレスが共有されます