ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScriptプロトタイププロパティの詳しい説明

JavaScriptプロトタイププロパティの詳しい説明

高洛峰
高洛峰オリジナル
2016-12-09 09:24:561435ブラウズ

各関数には、オブジェクトへの参照であるプロトタイプ属性があります。このオブジェクトはプロトタイプ オブジェクトと呼ばれます。プロトタイプ オブジェクトには、関数インスタンスによって共有されるメソッドとプロパティが含まれます。つまり、関数はコンストラクター呼び出しとして使用されます (new を使用)。オペレーター呼び出し)、新しく作成されたオブジェクトはプロトタイプ オブジェクトからプロパティとメソッドを継承します。

プライベート変数と関数
プロトタイプについて詳しく話す前に、プロトタイプの設計意図をよりよく理解できるように、関連するいくつかのことについて話しましょう。以前に書いた JavaScript 名前空間のブログでは、JavaScript の関数スコープについて言及しましたが、関数内で定義された変数や関数が外部へのインターフェイスを提供しない場合、それらは外部からアクセスできなくなります。つまり、プライベート変数になります。そしてプライベートな機能。

function Obj(){
    var a=0; //私有变量
    var fn=function(){ //私有函数
      
    }
   }

このように、変数 a と関数 fn は関数オブジェクト Obj の外部からはアクセスできなくなり、関数 Obj のインスタンスであってもこれらの変数や関数にはアクセスできなくなります。

var o=new Obj();
   console.log(o.a); //undefined
   console.log(o.fn); //undefined

静的変数と関数


関数が定義され、「.」を介してそれに追加された属性と関数にはオブジェクト自体からアクセスできますが、そのインスタンスにはアクセスできません。それぞれ静的変数と静的関数と呼ばれます。Java と C# を使用したことのある学生は、静的の意味を簡単に理解できます。

function Obj(){
     
   }
    
   Obj.a=0; //静态变量
    
   Obj.fn=function(){ //静态函数
      
   }
    
   console.log(Obj.a); //0
   console.log(typeof Obj.fn); //function
    
   var o=new Obj();
   console.log(o.a); //undefined
   console.log(typeof o.fn); //undefined

インスタンス変数、関数


オブジェクト指向プログラミングでは、いくつかのライブラリ関数に加えて、オブジェクトの定義時に同時にアクセスできるいくつかのプロパティとメソッドを定義したいと考えています。インスタンス化後、JavaScript でもこれを行うことができます

function Obj(){
    this.a=[]; //实例变量
    this.fn=function(){ //实例方法
      
    }
   }
    
   console.log(typeof Obj.a); //undefined
   console.log(typeof Obj.fn); //undefined
    
   var o=new Obj();
   console.log(typeof o.a); //object
   console.log(typeof o.fn); //function

これで上記の目的を達成できます

function Obj(){
    this.a=[]; //实例变量
    this.fn=function(){ //实例方法
      
    }
   }
    
   var o1=new Obj();
   o1.a.push(1);
   o1.fn={};
   console.log(o1.a); //[1]
   console.log(typeof o1.fn); //object
   var o2=new Obj();
   console.log(o2.a); //[]
   console.log(typeof o2.fn); //function

上記のコードの実行結果は完全に期待どおりですが、問題も示しています。と fn は o1 では変更されますが、o2 では変更されません。配列と関数はどちらもオブジェクトであり参照型であるため、o1 のプロパティとメソッドは o2 のプロパティとメソッドと同じ名前を持ちますが、それらは同じであることを意味します。参照ではなく、Obj オブジェクトのコピーによって定義されたプロパティとメソッドへの参照です。

これは属性の問題ではありませんが、メソッドにとっては大きな問題です。メソッドはまったく同じ機能を実行しますが、関数オブジェクトに数千のインスタンス メソッドがある場合、その各インスタンスにはコピーが 2 つ存在するためです。何千ものメソッドのコピーを維持しなければならないのですが、これは明らかに非科学的です。プロトタイプが誕生しました。

prototype


新しい関数が作成されるたびに、特定のルールに従ってその関数のプロトタイプ属性が作成されます。デフォルトでは、プロトタイプ属性はコンストラクター属性を取得します。この属性はポインターです。プロトタイプ属性が配置されている関数にコードを記述して、上の図を見てください。

function Person(){
     
   }

JavaScriptプロトタイププロパティの詳しい説明

上の図からわかるように、 person オブジェクトは、prototype 属性を自動的に取得します。また、prototype もオブジェクトであり、 Person オブジェクトを指すコンストラクター属性を自動的に取得します。

インスタンスを作成するためにコンストラクターが呼び出されるとき、インスタンスにはコンストラクターのプロトタイプを指す内部ポインター (多くのブラウザーではこのポインターは __proto__ という名前) が含まれます。この接続はインスタンスとコンストラクターのプロトタイプの間に存在します。インスタンスとコンストラクターの間ではありません。

function Person(name){
    this.name=name;
   }
    
   Person.prototype.printName=function(){
    alert(this.name);
   }
    
   var person1=new Person('Byron');
   var person2=new Person('Frank');

JavaScriptプロトタイププロパティの詳しい説明

person インスタンス person1 には name 属性が含まれており、また、Person のプロトタイプを指す __proto__ 属性も自動的に生成され、プロトタイプで定義されている printName メソッドにアクセスできます。おそらく次のようになります。

JavaScriptプロトタイププロパティの詳しい説明

テストするプログラムを書いて、プロトタイプ内のプロパティとメソッドが共有できるかどうかを確認してください

function Person(name){
    this.name=name;
   }
    
   Person.prototype.share=[];
    
   Person.prototype.printName=function(){
    alert(this.name);
   }
    
   var person1=new Person('Byron');
   var person2=new Person('Frank');
    
   person1.share.push(1);
   person2.share.push(2);
   console.log(person2.share); //[1,2]

案の定!実際、コードはオブジェクトの属性を読み取るときに、指定された名前の属性から検索を実行します。その属性がインスタンス内で見つかった場合は、その属性が検索されます。そうでない場合は、プロトタイプが検索され、まだ見つからない場合は、再帰後にオブジェクトが見つからない場合は、プロトタイプのオブジェクトを再帰し続けます。同様に、インスタンスにプロトタイプと同名のプロパティや関数が定義されている場合、プロトタイプのプロパティや関数は上書きされます。

function Person(name){
    this.name=name;
   }
    
   Person.prototype.share=[];
 
   var person=new Person('Byron');
   person.share=0;
    
   console.log(person.share); //0而不是prototype中的[]

単純なオブジェクトの構築


もちろん、プロトタイプは上記の問題を解決するために特別に定義されているわけではありませんが、上記の問題を解決します。この知識を理解すると、インスタンス オブジェクトのプロパティや関数が必要な場合は、プロトタイプで定義し、各インスタンスに個別のプロパティやメソッドを持たせたい場合は、これをインスタンス化して定義します。パラメータはコンストラクタを介して渡すことができます。

りー


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