Javascriptは対象に向かってプログラミングします.

4464 ワード

Javascriptは対象(object-based)に基づく言語で、あなたが出会うすべてのものはほとんど対象です.しかし、それは本物のオブジェクト向けプログラミング(OOP)言語ではないです.その文法にはクラスがないからです.
では、もし私たちが「属性」と「方法」を一つのオブジェクトにパッケージ化し、さらに原型のオブジェクトから具体的なオブジェクトを生成するなら、どうすればいいですか?
一、オブジェクトを生成する元のパターン
猫を対象とすると、名前と色の2つの属性があります.
  var Cat = {
    name : '',
    color : ''
  }
今はこのプロトタイプオブジェクトの仕様に基づいて、二つのインスタンスオブジェクトを生成する必要があります.
  var cat1 = {}; //        
    cat1.name = "  "; //            
    cat1.color = "  ";
  var cat2 = {};
    cat2.name = "  ";
    cat2.color = "  ";
はい、これは一番簡単なパッケージです.二つの属性を一つのオブジェクトに入れます.しかし、このような書き方には二つの欠点があります.一つは、いくつかの例を多く作ると、書くのが面倒くさいです.二つ目は実例と原型の間で、何の方法もなく、何の連絡があるかを確認できます.
二、オリジナルモードの改善
コード重複の問題を解決する関数を書くことができます.
  function Cat(name,color){
    return {
      name:name,
      color:color
    }
  }
次にインスタンスオブジェクトを生成すると、関数を呼び出しているのと同じです.
  var cat1 = Cat("  ","  ");
  var cat2 = Cat("  ","  ");
この方法の問題は依然として、cat 1とcat 2の間に内在的な連絡がなく、それらが同じプロトタイプのオブジェクトである例を反映することができない.
三、コンストラクタモード
プロトタイプオブジェクトからインスタンスを生成する問題を解決するために、Javascriptはコンストラクションモードを提供する.
「構造関数」というのは普通の関数ですが、内部ではthis変数が使われています.構造関数にnew演算子を使うと、インスタンスが生成され、this変数はインスタンスオブジェクトに結合されます.
例えば、猫の原型の対象は現在このように書くことができます.
  function Cat(name,color){
    this.name=name;
    this.color=color;
  }
私たちは今すぐにインスタンスオブジェクトを生成できます.
  var cat1 = new Cat("  ","  ");
  var cat2 = new Cat("  ","  ");
  alert(cat1.name); //   
  alert(cat1.color); //   
このときcat 1とcat 2は、自動的にconstructor属性を含み、それらの構造関数を指す.
  alert(cat1.constructor == Cat); //true
  alert(cat2.constructor == Cat); //true
Javascriptはまた、プロトタイプオブジェクトとインスタンスオブジェクトとの関係を検証するinstance of演算子を提供する.
  alert(cat1 instanceof Cat); //true
  alert(cat2 instanceof Cat); //true
四、コンストラクタモードの問題
コンストラクター法は使いやすいですが、メモリを浪費する問題があります.
見てください.今はCatの対象に不変の属性「type」を追加して、もう一つの方法を追加します.モデル対象のCatは次のようになります.
  function Cat(name,color){
    this.name = name;
    this.color = color;
    this.type = "    ";
    this.eat = function(){alert("   ");};
  }
それとも同じ方法を採用して、インスタンスを生成しますか?
  var cat1 = new Cat("  ","  ");
  var cat2 = new Cat ("  ","  ");
  alert(cat1.type); //     
  cat1.eat(); //    
表面的には問題がないようですが、実際にこのようにすると、大きな弊害があります.それは、各インスタンスオブジェクトに対して、type属性とeat()方法は同じ内容であり、毎回インスタンスを生成するには、重複した内容のためにメモリを多く占用しなければならない.これは環境にもやさしいし、効率にも欠ける.
  alert(cat1.eat == cat2.eat); //false
type属性とeat()メソッドをメモリに一度だけ生成して、そのメモリアドレスをすべて指してもいいですか?答えは大丈夫です.
五、Prottypeモード
Javascriptは、各構造関数にプロタイプの属性があり、他のオブジェクトを指すと規定しています.このオブジェクトのすべての属性と方法は、構造関数の例によって継承されます.
これは、私達がこれらの不変の属性と方法を直接prototypeオブジェクトに定義することができるという意味です.
  function Cat(name,color){
    this.name = name;
    this.color = color;
  }
  Cat.prototype.type = "    ";
  Cat.prototype.eat = function(){alert("   ")};
その後、インスタンスを生成する.
  var cat1 = new Cat("  ","  ");
  var cat2 = new Cat("  ","  ");
  alert(cat1.type); //     
  cat1.eat(); //    
この場合、すべてのインスタンスのtype属性とeat()メソッドは、同じメモリアドレスで、prototypeオブジェクトを指すので、動作効率が向上します.
  alert(cat1.eat == cat2.eat); //true
六、Prottypeモードの検証方法
プロトタイプの属性に合わせるために、Javascriptはいくつかの補助方法を定義しています.
6.1 isPrototypeOf()
この方法は、あるproptotypeオブジェクトとあるインスタンスとの関係を判断するために用いられます.
  alert(Cat.prototype.isPrototypeOf(cat1)); //true
  alert(Cat.prototype.isPrototypeOf(cat2)); //true
6.2ハスOwnProperty()
各インスタンスオブジェクトには、ある属性がローカル属性なのか、それともプロトタイプオブジェクトからの属性なのかを判断するためのハスOwnProperty()方法があります.
  alert(cat1.hasOwnProperty("name")); // true
  alert(cat1.hasOwnProperty("type")); // false
6.3 in演算子
in演算子は、ローカル属性ではなく、あるインスタンスに属性が含まれているかどうかを判断するために使用されてもよい.
  alert("name" in cat1); // true
  alert("type" in cat1); // true
in演算子は、あるオブジェクトのすべての属性を巡回するためにも使用できます.
  for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }