ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript学習メモ(5) プロトタイプとプロトタイプチェーンの詳細解説_基礎知識
プライベート変数と関数
関数内で定義された変数と関数は、外部へのインターフェイスが提供されていない場合、つまり変数と関数が関数に対してプライベートである場合、外部からアクセスすることはできません。
}
}
このようにして、変数 color と fn は関数オブジェクト Test の外部からアクセスできなくなり、プライベートになります:
静的変数と静的関数
関数が定義され、ドット「.」によって追加された属性と関数はオブジェクト自体からアクセスできますが、そのインスタンスにはアクセスできない場合、そのような変数と関数はそれぞれ静的変数と静的関数と呼ばれます。
}
Obj.num = 72;//静的変数
Obj.fn = function() //静的関数
{
}
alert(Obj.num);//72
alert(obj.fn の種類)//function
var t = new Obj();
alert(t.name);//未定義
alert(typeof t.fn);//未定義
インスタンス変数と関数
オブジェクト指向プログラミングでは、いくつかのライブラリ関数に加えて、オブジェクトの定義時にいくつかのプロパティとメソッドを定義することが望まれます。これらはインスタンス化後にアクセスできます。
}
}
console.log(obj.a の種類) //未定義
console.log(Obj.fn のタイプ); //未定義
var o=new Obj();
console.log(typeof o.a); //オブジェクト
console.log(typeof of.fn); //関数
インスタンス変数とメソッドの新しいメソッドとプロパティを追加します
}
}
var o1=new Obj();
o1.a.push(1);
o1.fn={};
console.log(o1.a); //[1]
console.log(o1.fn のタイプ); //オブジェクト
var o2=new Obj();
console.log(o2.a); //[]
console.log(o2.fn のタイプ); //関数
a と fn は o1 では変更されますが、o2 では変更されません。配列と関数はどちらもオブジェクトであり参照型であるため、o1 のプロパティとメソッドは o2 のものと同じ名前ですが、ただし、これは参照ではなく、Obj オブジェクトによって定義されたプロパティとメソッドのコピーです。
これは属性にとっては問題ではありませんが、メソッドにとっては大きな問題です。メソッドはまったく同じ機能を実行しますが、関数オブジェクトに 1000 のメソッドとインスタンスのメソッドがある場合、それぞれのインスタンスが 2 回コピーされるからです。何千ものメソッドのコピーを維持する必要がありますが、これは明らかに非科学的です。プロトタイプが誕生しました。
基本概念
私たちが作成するすべての関数には、オブジェクトへのポインターであるプロトタイプ属性があります。このオブジェクトの目的は、特定の型のすべてのインスタンスで共有できるプロパティとメソッドを含めることです。そして、prototypeはコンストラクタを呼び出して作成されるオブジェクトインスタンスのプロトタイプオブジェクトです。
プロトタイプを使用する利点は、オブジェクト インスタンスがそれに含まれるプロパティとメソッドを共有できることです。つまり、コンストラクターに定義オブジェクト情報を追加する代わりに、この情報をプロトタイプに直接追加できます。コンストラクターを使用する場合の主な問題は、各インスタンスで各メソッドを作成する必要があることです。
JavaScriptには、プリミティブ値とオブジェクト値の2種類の値があります。すべてのオブジェクトには、通常プロトタイプと呼ばれる内部プロパティ プロトタイプがあります。プロトタイプの値はオブジェクトまたは null にすることができます。その値がオブジェクトの場合、そのオブジェクトにも独自のプロトタイプが必要です。これにより、プロトタイプ チェーンと呼ばれる線形チェーンが形成されます。
意味
関数はコンストラクターとして使用できます。さらに、関数のみがプロトタイプ属性を持ち、アクセスできますが、オブジェクト インスタンスにはこの属性はなく、アクセスできない内部の __proto__ 属性のみが存在します。 __proto__ は、オブジェクト内の関連するプロトタイプへの暗号的なリンクです。標準によれば、__proto__ は公開されていません。つまり、プライベート プロパティですが、Firefox エンジンは、外部からアクセスして設定できるパブリック プロパティとして公開します。
var Bro = 新しいブラウザ();
Bro.run();
Bro.run() メソッドを呼び出すと、Bro にはそのようなメソッドがないため、その __proto__ にアクセスしてそれを見つけます。これが Browser.prototype であり、最終的に run() メソッドが実行されます。 (ここでは、通常の関数と区別するため、関数の最初の文字を大文字でコンストラクタを表します)
インスタンスを作成するためにコンストラクターが呼び出されるとき、インスタンスにはコンストラクターのプロトタイプを指す内部ポインター (__proto__) が含まれます。この接続は、インスタンスとコンストラクターのプロトタイプの間に存在します。インスタンスとコンストラクターの間には存在しません。コンストラクター。
person.prototype.printName=function(){
アラート(this.name);
}
var person1=新しい人('バイロン');
var person2=新しい人('フランク');
person インスタンス person1 には name 属性が含まれており、自動的に __proto__ 属性を生成します。これは、おそらく次のようなプロトタイプで定義された printName メソッドにアクセスできます。
別の例:
{
alert("これは " this.name);
}
var Cat = new Animal("cat");//猫オブジェクトを作成します
Cat.behavior();//「これは猫です」を出力
配列オブジェクトインスタンス
配列オブジェクトの例を見てください。オブジェクト array1 を作成するとき、JavaScript エンジンにおける array1 の実際のオブジェクト モデルは次のようになります:
array1 オブジェクトの長さ属性値は 3 ですが、次のメソッドを通じて array1 に要素を追加できます:
array1.push(4); Push メソッドは、array1 の __proto__ メンバーが指すメソッド (Array.prototye.push()) から取得されます。すべての配列オブジェクト ([] によって作成されたもの) には、プッシュ、リバース、その他のメソッドで同じオブジェクト (Array.prototype) を指す __proto__ メンバーが含まれているため、これらの配列オブジェクトはプッシュ、リバース、その他のメソッドを使用できます。
新しいオペレーターは具体的に何をするのですか? それは実際には非常に単純で、3 つのことを行います。
プロトタイプ チェーン: オブジェクトからプロパティまたはメソッドを呼び出すとき、オブジェクト自体にそのようなプロパティまたはメソッドがない場合、プロトタイプにプロパティまたはメソッドがない場合は、関連付けられたプロトタイプ オブジェクトに移動して探します。プロトタイプの関連付けに移動して、前のプロトタイプを検索し、それ以上ない場合は、Prototype...Prototype が未定義になるまで (オブジェクトのプロトタイプが未定義になるまで) Prototype.Prototype によって参照されるオブジェクトの検索を続けます。 )、いわゆる「プロトタイプチェーン」を形成します。
TwoShape.prototype.constructor = TwoShape;
var my = new Triangle(5,10);
My.toString();//Triangle
My.constructor;//Triangle(side,height)
プロトタイプの継承: プロトタイプ チェーンの最後にあるのは、オブジェクト コンストラクターのプロトタイプ属性によって指定されるプロトタイプ オブジェクトです。このプロトタイプ オブジェクトはすべてのオブジェクトの祖先であり、すべてのオブジェクトが本質的に持つべき toString などのメソッドを実装します。 Function、Boolean、String、Date、RegExp などの他の組み込みコンストラクターのプロトタイプはすべてこの祖先から継承されていますが、それらはそれぞれ独自のプロパティとメソッドを定義しているため、子孫はそれぞれのクランの特性を示します。それらの特徴。
ECMAScript では、継承を実装する方法はプロトタイプ チェーンに依存することです。
function Tree(){ //継承された関数はサブタイプ(サブクラス、派生クラス)と呼ばれます
This.age = 300;
}
//プロトタイプチェーンの継承を通じて、サブタイプのプロトタイププロパティに値を割り当てます
//new Box() はボックス構造内の情報とプロトタイプを Tree
に渡します
Tree.prototype = new Box();//Tree は Box を継承し、プロトタイプを通じてチェーンを形成します
var ツリー = new Tree();
alert(tree.name);//ポップアップジャック
プロトタイプ チェーンの問題: プロトタイプ チェーンは非常に強力で、継承の実装に使用できますが、いくつかの問題もあります。そのうちの主なものは、参照型を含む値プロトタイプに由来します。参照型を含むプロトタイプ プロパティはすべてのインスタンスで共有されます。これが、プロパティがプロトタイプ オブジェクトではなくコンストラクターで定義される理由です。プロトタイプを介して継承が実装されると、プロトタイプは実際には別の型のインスタンスに戻ります。その結果、元のインスタンス プロパティがプロトタイプ プロパティになります。
サブタイプのインスタンスを作成する場合、パラメーターをスーパータイプのコンストラクターに渡すことはできません。実際、すべてのオブジェクト インスタンスに影響を与えずにスーパータイプのコンストラクターにパラメーターを渡す方法はないと言うべきです。プロトタイプに参照型の値が含まれるために今説明した問題と相まって、プロトタイプ チェーンだけが実際に使用されることはほとんどありません。
別の例:
person.prototype.company = "Microsoft";//プロトタイプのプロパティを設定します
Person.prototype.SayHello = function() //プロトタイプメソッド
{
alert("こんにちは、" this.company の " this.name " です);
};
var BillGates = new Person("BillGates");//人物オブジェクトを作成します
BillGates.SayHello();//プロトタイプの内容を継承し、「こんにちは、Microsoft の BillGates です」を出力します
var Jobs = new Person("Jobs");
Jobs.company = "Apple";//プロトタイプの会社属性をカバーして、独自の会社属性を設定します
Jobs.SayHello = function()
{
alert("こんにちは、" this.name " like " this.company);
};
Jobs.SayHello();//属性とメソッドを自分でオーバーライドし、「Hi, Jobs like Apple」を出力します
BillGates.SayHello();//ジョブのカバレッジはプロトタイプには影響せず、BillGates は引き続き
を出力します
次のプロトタイプ チェーンの例を見てください:
}
};
関数 Hi(){
};
//Hi のプロトタイプ属性を Year
のインスタンス オブジェクトに設定します
Hi.prototype = new Year();
Hi.prototype.year = 'Hello World';
Hi.prototype.constructor = こんにちは;
var test = new Hi();//Hi の新しいインスタンスを作成します
//プロトタイプチェーン
[こんにちはインスタンス] をテストします
Hi.prototype [年のインスタンス]
{年:'Hello World'}
年.プロトタイプ
に
object.prototype
__ptoto__ 属性 (IE ブラウザではサポートされていません) は、インスタンスからプロトタイプ オブジェクトへのポインターであり、その機能は、コンストラクターのプロトタイプ属性コンストラクターを指すことにより、属性とメソッドにアクセスできます。プロトタイプでは。
JavaScript のオブジェクト インスタンスは、基本的に一連の属性で構成されます。これらの属性の中に、内部の目に見えない特別な属性 (__proto__) があり、この属性の値はオブジェクト インスタンスのみが持つプロトタイプを指します。ユニークなプロトタイプ。
//関数はプロトタイプ ポインターによって配置され、コンストラクター自体を取得します
スクリプト>
プロトタイプは関数オブジェクトの独自の属性です。 __proto__ は通常のオブジェクトの暗黙的な属性です。 new を使用すると、
が指すオブジェクトを指します。 __ptoto__ は実際にはエンティティ オブジェクトの属性ですが、プロトタイプはコンストラクターに属する属性です。 __ptoto__ は学習環境またはデバッグ環境でのみ使用できます。
プロトタイプモードの実行プロセス
2. コンストラクターのインスタンスがない場合は、そのプロトタイプ オブジェクト内でそれを探します。存在する場合は、すぐに戻ります
。 プロトタイプオブジェクトの
alert(box1.name);//trigkit4、プロトタイプの値
box1.name = "リー";
alert(box1.name);//リー、原則を入力してください
alert(box2.name);//trigkit4、プロトタイプ値はbox1
によって変更されていません
コンストラクターの
Box.prototype.run = function()//プロトタイプメソッド
{
return this.name this.age '勉強中';
}
var box1 = new Box();
box1.name = "リー";
alert(box1.name);//リー、原則を入力してください