JavaScriptのプロトタイプは理解しにくい部分ですが、ここではいくつかの重要な知識ポイントを通してJSのプロトタイプについて説明します。具体的な内容については、以下の詳細をご覧ください。
1 プロトタイプデザインパターン
clone() を使用して .Net にプロトタイプ メソッドを実装できます
プロトタイプ メソッドの主なアイデアは、クラス A が存在し、クラス B を作成したいということです。このクラスは A に基づいており、拡張できます。 B のプロトタイプを A と呼びます。
2 JavaScript メソッドは 3 つのカテゴリに分類できます:
クラスメソッド
b オブジェクトメソッド
c プロトタイプメソッド
例:
function People(name) { this.name=name; //对象方法 this.Introduce=function(){ alert("My name is "+this.name); } } //类方法 People.Run=function(){ alert("I can run"); } //原型方法 People.prototype.IntroduceChinese=function(){ alert("我的名字是"+this.name); } //测试 var p1=new People("Windking"); p1.Introduce(); People.Run(); p1.IntroduceChinese();
3 obj1.func.call(obj) メソッド
obj を obj1 として扱い、func メソッドを呼び出すことを意味します
それでは、問題を 1 つずつ解決していきましょう:
プロトタイプとはどういう意味ですか?
JavaScript のすべてのオブジェクトにはプロトタイプ属性があります。JavaScript のオブジェクトのプロトタイプ属性の説明は次のとおりです。オブジェクト型のプロトタイプへの参照を返します。
A.prototype = new B();
プロトタイプを理解することを継承と混同しないでください。 A のプロトタイプは B のインスタンスです。A が B のすべてのメソッドとプロパティを複製したことがわかります。 A は B のメソッドとプロパティを使用できます。ここでは、継承ではなくクローン作成に重点を置いています。このような状況が発生する可能性があります。A のプロトタイプは B のインスタンスであり、B のプロトタイプも A のインスタンスです。
実験例を見てみましょう:
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); // 显示baseClass::showMsg
最初にbaseClassクラスを定義し、次にextentClassを定義しますが、baseClassのインスタンスをプロトタイプとして使用する予定で、複製されるextendedClassにはshowMsgオブジェクトのメソッドも含まれています。
extendClass.prototype = newbaseClass() は次のように読み取ることができます。 extendClass は、baseClass のインスタンスをプロトタイプとして複製することによって作成されます。
次に、extendClass 自体に、baseClass のメソッドと同じ名前のメソッドが含まれている場合はどうなるかという疑問が生じます。
以下は拡張実験 2 です:
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg();//显示extendClass::showMsg
実験的証明: 関数の実行中は、まずオントロジーで関数が検索され、見つからない場合はプロトタイプで関数が検索されます。あるいは、プロトタイプが同じ名前の関数を複製しないことも理解できます。
その後、新しい質問が表示されます:
extendClass のインスタンスを使用して、baseClass のオブジェクト メソッド showMsg を呼び出したい場合はどうすればよいですか?
答えは、通話を使用することです:
extendClass.prototype = new baseClass(); var instance = new extendClass(); var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg
ここでのbaseinstance.showMsg.call(instance)は、「インスタンスをbaseinstanceとして呼び出し、そのオブジェクトメソッドshowMsgを呼び出します」
それでは、baseClass.showMsg.call(instance);
をなぜ使用しないのかと尋ねる人もいるかもしれません。これは、オブジェクト メソッドとクラス メソッドの違いです。呼び出したいのは、baseClass
のオブジェクト メソッドです。最後に、次のコードを明確に理解できれば、この記事の内容を理解できると思います。
<script type="text/javascript"> function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } this.baseShowMsg = function() { alert("baseClass::baseShowMsg"); } } baseClass.showMsg = function() { alert("baseClass::showMsg static"); } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.showMsg = function() { alert("extendClass::showMsg static") } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); //显示extendClass::showMsg instance.baseShowMsg(); //显示baseClass::baseShowMsg instance.showMsg(); //显示extendClass::showMsg baseClass.showMsg.call(instance);//显示baseClass::showMsg static var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg </script>
ps: js プロトタイプ属性の説明と共通メソッド
機能: プロトタイプ
各コンストラクターにはプロトタイプと呼ばれる属性があります (プロトタイプは以下では翻訳されませんので、オリジナルのテキストを使用します)。この属性は、特定のクラスの共通の変数または関数を宣言する場合に非常に役立ちます。
プロトタイプの定義
プロトタイプ属性はすべてのコンストラクターに存在するため、明示的に宣言する必要はありません。次の例を見てみましょう:
例 PT1
コード:
function Test() { } alert(Test.prototype); // 输出 "Object"
プロトタイプに属性を追加します
上でわかるように、プロトタイプはオブジェクトであるため、プロパティを追加できます。プロトタイプに追加したプロパティは、このコンストラクターを使用して作成されたオブジェクトの共通プロパティになります。
たとえば、以下のデータ型 Fish があり、すべての Fish に次の属性を持たせたいとします。これを実現するには、コンストラクター Fish のプロトタイプにこれらの属性を追加します。
例 PT2
コード:
function Fish(name, color) { this.name=name; this.color=color; } Fish.prototype.livesIn="water"; Fish.prototype.price=20;
次は魚を作りましょう:
コード:
var fish1=new Fish("mackarel", "gray"); var fish2=new Fish("goldfish", "orange"); var fish3=new Fish("salmon", "white");
魚の属性を見てみましょう:
コード:
for (int i=1; i<=3; i++) { var fish=eval_r("fish"+i); // 我只是取得指向这条鱼的指针 alert(fish.name+","+fish.color+","+fish.livesIn+","+fish.price); }
出力は次のようになります:
コード:
"mackarel, gray, water, 20" "goldfish, orange, water, 20" "salmon, white water, 20"
你看到所有的鱼都有属性livesIn和price,我们甚至都没有为每一条不同的鱼特别声明这些属性。这时因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。
你也可以通过prototype来给所有对象添加共用的函数。这有一个好处:你不需要每次在构造一个对象的时候创建并初始化这个函数。为了解释这一点,让我们重新来看Example DT9并使用prototype来重写它:
用prototype给对象添加函数
Example PT3
CODE:
function Employee(name, salary) { this.name=name; this.salary=salary; } Employee.prototype.getSalary=function getSalaryFunction() { return this.salary; } Employee.prototype.addSalary=function addSalaryFunction(addition) { this.salary=this.salary+addition; }
我们可以象通常那样创建对象:
CODE:
var boss1=new Employee("Joan", 200000); var boss2=new Employee("Kim", 100000); var boss3=new Employee("Sam", 150000);
并验证它:
CODE:
alert(boss1.getSalary()); // 输出 200000 alert(boss2.getSalary()); // 输出 100000 alert(boss3.getSalary()); // 输出 150000
这里有一个图示来说明prototype是如何工作的。这个对象的每一个实例(boss1, boss2, boss3)都有一个内部属性叫做__proto__,这个属性指向了它的构造器(Employee)的属性prototype。当你执行 getSalary或者addSalary的时候,这个对象会在它的__proto__找到并执行这个代码。注意这点:这里并没有代码的复制(和 Example DT8的图表作一下对比)。