ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScriptでのプロトタイプ解析【推奨】_javascriptスキル

JavaScriptでのプロトタイプ解析【推奨】_javascriptスキル

WBOY
WBOYオリジナル
2016-05-16 15:02:091301ブラウズ

最近、JavaScript と js オブジェクト指向のプロトタイプを学んでいて、多くのことを学びました。何か間違っているところがあれば、修正していただければ幸いです。

jsはオブジェクト指向言語なので当然継承の概念がありますが、jsにはクラスの概念がなく、javaのようなextendsもないので、jsの継承は主にプロトタイプ(チェーン)に依存していると思います。 )jsで。

では、プロトタイプとは何でしょうか? js の関数もオブジェクトであることがわかります。関数を作成するとき、その関数にはデフォルトでプロトタイプと呼ばれる属性があり、これは関数のプロトタイプを指すポインターです。 . オブジェクト、このプロトタイプ オブジェクトには、protptype 属性を持つ関数を指すコンストラクターと呼ばれるデフォルトの属性があります。

function Person(){}
    Person.prototype={
     // constructor:Person;
      first_name:"guo",
      hair_color:"black",
      city:"zhengzhou",
      act:function(){alert("eatting");}
    };

これを例として考えます。まず、関数 person を作成します。この関数には、デフォルトの属性プロトタイプがあり、そのオブジェクトは Person.propttype オブジェクトを指します。このオブジェクトには、デフォルトの属性コンストラクター () が含まれています。 >人 (実際、ここでのデフォルトはオブジェクトを指すことになっています。後で修正します)

コンストラクターを通じてインスタンスを作成すると何が起こるでしょうか?

function Person(){} 
  Person.prototype={ 
    first_name:"guo", 
    hair_color:"black", 
    city:"zhengzhou", 
    act:function(){alert("eatting");} 
  }; 
  var boy=new Person(); 
  var girl=new Person(); 

このとき、js のコンストラクターと関数の違いは new キーワードであり、new 演算子を使用する関数がコンストラクターであることを知っておく必要があります。 Person のインスタンス オブジェクトを作成し、boy と girl で保存すると、これら 2 つのインスタンス オブジェクトは _proto_ というデフォルト属性を生成します (これは ECMAScript5 では [[prototype]] で表すことができます)。この属性はコンストラクターのプロトタイプを指します。関数のオブジェクト、boy._proto_--->person.prototype (コンストラクターとは関係ありません)。このとき、男の子または女の子はプロトタイプ オブジェクトの属性をドットを通じて呼び出すことができます。このとき、男の子と女の子がプロトタイプ オブジェクトの属性を共有していることを知っておく必要があります。上記の結論は、isProtptypeOf() または object.getPrototypeOf() を通じて検証できます (この関数の戻り値はプロトタイプ オブジェクト、つまり _proto_ の値です)。

alert(Person.prototype.isPrototypeOf(boy)); //true 
alert(Object.getPrototypeOf(boy).first_name);  //"guo" 

この時点で、プロトタイプ オブジェクトのプロパティと同じ名前のプロパティがインスタンスに作成された場合はどうなるかをさらに検証できます。

var boy=new Person(); 
var girl=new Person(); 
boy.hair_color="red";  
alert(boy.hair_color);  //red 
alert(girl.hair_color); //black 
alert(Object.getPrototypeOf(boy).hair_color);  //black 

インスタンスで宣言された同じ名前の属性がプロトタイプ オブジェクトの属性をブロックすることがわかりますが、それは一時的に上書きされるだけで、プロトタイプ オブジェクトの属性の型には影響しません (Object.getPrototypeOf( boy).hair_color== black)、プロトタイプ オブジェクト プロパティ タイプ (girl.hair_color== black) を共有する他のインスタンス オブジェクトには影響しません。同時に、delete 演算子を使用してインスタンス オブジェクトによって宣言された属性を削除し、ブロック効果をキャンセルすることができます。 hasOwnProperty() を使用すると、プロパティがインスタンスに存在するか (true)、プロトタイプ オブジェクトに存在するか (false) を確認できます。

alert(boy.hasOwnProperty("hair_color")); //true

プロパティは Object.keys() を使用して列挙できます。

var key=Object.keys(Person.prototype); 
alert(key); 

これを学習すると、プロトタイプ オブジェクトを宣言するために上記の記述方法を使用すると、コンストラクターが person を指さなくなるという問題が発生することがわかります。これは、プロトタイプ オブジェクトのコンストラクター属性が指すという前述の内容に反します。これは、関数が作成されるたびにプロトタイプ オブジェクトが自動的に作成され、このオブジェクトがデフォルトでコンストラクターを作成するためです。したがって、ここでの本質は、デフォルトのプロトタイプを書き直すことです。これにより、新しいコンストラクタも Object 関数を指すようになり、Person 関数を指すことがなくなります。コンストラクターが本当に重要な場合は、constructor:Person と記述する必要があります。

その後、プロトタイプ オブジェクトのプロパティの種類を変更する前にインスタンスが作成されたか変更された後にインスタンスが作成されたかに関係なく、プロトタイプ オブジェクトのプロパティの変更がインスタンスに反映されることを知る必要があります。 🎜>

function Person(){} 
Person.prototype={ 
  first_name:"guo", 
  hair_color:"black", 
  city:"zhengzhou", 
  act:function(){alert("eatting");} 
}; 
 
var boy=new Person(); 
Person.prototype.hobby="basketball"; 
var girl=new Person(); 
alert(boy.hobby); //basketball 
上記のコードからわかるように、インスタンスの作成後にプロトタイプ オブジェクトのプロパティの変更が行われた場合でも、boy インスタンスは引き続き Person.prototype.hobby を共有します。

ただし、この状況は、プロトタイプ オブジェクトのプロパティが変更された場合にのみ発生します。プロトタイプ オブジェクトのプロパティが完全に書き換えられた場合、インスタンスの作成は、プロトタイプ オブジェクトのプロパティが書き換えられた後に配置する必要があります。そうしないと、エラーが発生します。


function Person(){} 
    var girl=new Person(); 
    Person.prototype={ 
      first_name:"guo", 
      hair_color:"black", 
      city:"zhengzhou", 
      act:function(){alert("eatting");} 
    }; 
 
    var boy=new Person(); 
    Person.prototype.hobby="basketball"; 
     
    alert(boy.hobby);  //basketball 
    alert(girl.first_name);  //undefined 
「シールド」の問題に戻りますが、インスタンス オブジェクトの属性 (プロトタイプ オブジェクト内の特定の属性と同じ名前を持つ) を作成すると、プロトタイプ オブジェクトの属性はブロックされますが、そうではありません。他のインスタンス オブジェクトに影響を与えます。ここにはエラーがあります。この状況は、属性の値が型を参照する場合にのみ当てはまります。次のコードを参照してください。

function Person(){}
    
    Person.prototype={
      first_name:"guo",
      hair_color:"black",
      friends:["Nick","John"],
      city:"zhengzhou",
      act:function(){alert("eatting");}
    };

    var boy=new Person();
    boy.friends.push("Mike");
    var girl=new Person();
    alert(boy.friends);  //Nick,John,Mike
    alert(girl.friends); //Nick,John,MIke
上記の文は当てはまらないことがわかります。その理由は、プロトタイプ オブジェクトには少年ではなく友人が存在するため、彼の変更はこの環境に影響を与えるからです。 (boy.frindes=[] を通じて、boy インスタンスの属性を作成できます。) 次に、コンストラクター モードとプロトタイプ モードの組み合わせを導入する必要があります。

function Person(hair_color,city){ 
       
      this.hair_color=hair_color; 
      this.city=city; 
      this.friends=["John","Nick"]; 
    } 
    Person.prototype={ 
      constructor:Person, 
      first_name:"guo", 
      act:function() { 
         
        alert("eatting"); 
      } 
    }; 
    var boy=new Person("black","zhengzhou"); 
    var girl=new Person("red","shenyang"); 
    boy.friends.push("Nick"); 
    alert(girl.friends); 
    alert(boy.friends); 

このモードは現在、ECMAScript でカスタム タイプを作成する方法として最も広く使用され認識されており、デフォルト モードとしても使用できます。

しかし、他のオブジェクト指向言語で作業しているプログラマーにとって、このパターンは、すべての情報をコンストラクターにカプセル化するために、動的プロトタイプ パターンが登場したのとは奇妙に思えます。動的モードでは、主に if ステートメントを使用して、リソースを節約するためにプロトタイプ オブジェクトを初期化する必要があるかどうかを判断します。

さらに、共有属性がなく、これが使用されない状況に適応するための安全な構築モードがあります。

上記の JavaScript でのプロトタイプ分析 [推奨] は、エディターによって共有されたすべての内容です。参考にしていただければ幸いです。スクリプト ホームをサポートしていただければ幸いです。

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