[JavaScript]対象に向ける


1.オブジェクトの作成
1.1 ECMAScriptの対象
ECMAScriptにはクラスの概念がありません.オブジェクトの定義は、無秩序属性のセットです.属性は基本値、オブジェクトまたは関数を含むことができます.オブジェクトに相当するグループは特定の順序がない値で、属性や方法には名前があります.各オブジェクトは一つの参照タイプに基づいて作成されます.
カスタムオブジェクトを作成する最も簡単な方法は、Objectのインスタンスを作成し、属性と方法を追加することです.
var myobj = new Object();
myobj.name = "object";
myobj.getName = function() {
  alert(this.name);
}
1.2工場モード
工場モデルはソフトウェア工学でよく知られている設計モデルであり、このモデルは具体的な対象を作る過程を抽象的に示している.ECMAScriptではクラスを作成できませんので、特定のインターフェースでオブジェクトを作成するための詳細を関数で実装することができます.
function createObject(name) {
  var myobj = new Object();
  myobj.name = "object";
  myobj.getName = function() {
    alert(this.name);
  }
  return myobj;
}
1.3コンストラクタモード
ECMAScriptの構造関数は、特定のタイプのオブジェクトを作成するために使用されます.例えば、ObjectやArayのようなオリジナルのコンストラクタを作成することができます.また、カスタムオブジェクトタイプの属性と方法を定義することもできます.
function Myobj(name) {
  this.name = name;
  this.getName = function() {
    alert(this.name);
  }
}
コンストラクタと他の関数との唯一の違いは、それらを呼び出す方法が違っていますが、コンストラクタも関数であり、コンストラクタを定義する特殊な文法は存在しません.どの関数も、newオペレータによって呼び出されれば、構造関数として機能することができますが、newオペレータを介して呼び出さないと、普通の関数と区別されません.
var myobj = new Myobj("object");
コンストラクタを使用する主要な問題は、各方法が各インスタンスで再作成されることであり、関数もオブジェクトであるため、関数を定義するごとに、オブジェクトを実例化することである.この問題を解決するには、関数の定義を外部に移すことができます.例えば、
function Myobj(name) {
  this.name = name;
  this.getName = getName;
}
function getName() {
  alert(this.name);
}
1.4プロトタイプモード
各関数にはプロトタイプの属性があり、この属性はオブジェクトを指すポインタであり、このオブジェクトの用途は特定のタイプのすべてのインスタンスで共有できる属性と方法を含む.プロトタイプオブジェクトを使用する利点は、すべてのオブジェクトインスタンスに、その中に含まれる属性および方法を共有させることである.
function Myobj() {
}
Myobj.prototype.name = "object";
Myobj.prototype.getName = function() {
  alert(this.name);
}
var myobj = new Myobj();
myobj.getName();
コードがあるオブジェクトの属性を読み取るたびに、まずオブジェクトのインスタンス自体から検索を開始します.インスタンスに名前が与えられた属性が見つかったら、属性の値を返します.見つけられなかったら、プロトタイプのオブジェクトを検索し続けます.オブジェクトのインスタンスに属性を追加すると、この属性はプロトタイプオブジェクトに保存されている同名の属性をブロックしますが、プロトタイプの中のその属性の値は変更されません.
function Myobj() {
}
Myobj.prototype.name = "object";
Myobj.prototype.getName = function() {
  alert(this.name);
}
var myobj1 = new Myobj();
var myobj2 = new Myobj();
myobj1.name = "new object";
例の属性はnullに設定されても、この属性はインスタンスにのみ設定され、プロトタイプへの接続を回復することはないが、deleteオペレータはインスタンス属性を完全に削除し、プロトタイプの属性に再アクセスすることができる.
function Myobj() {
}
Myobj.prototype.name = "object";
Myobj.prototype.getName = function() {
  alert(this.name);
}
var myobj1 = new Myobj();
var myobj2 = new Myobj();
myobj1.name = "new object";
delete myobj1.name;
hasOwnProperty()方法を使用して、属性がインスタンスに存在するか、それともプロトタイプに存在するかを検出し、所与の属性がオブジェクトインスタンスに存在する限り、trueに戻ります.
alert(myobj.hansOwnProperty("name"));
inオペレータは、オブジェクトを介して指定された属性にアクセスできるときにtrueを返します.インスタンスに関係なく、またはプロトタイプに存在します.例えば、
alert("name" in myobj);
すべてのオリジナル引用タイプは、プロトタイプを用いて作成され、その構造関数のプロトタイプに方法が定義されています.例えば、
alert(typeof String.prototype.substring);
プロトタイプモードの欠点は、プロトタイプのすべての属性が多くのインスタンスに共有され、参照タイプの値を含む属性について、例えば、
function Myobj() {
}
Myobj.prototype = {
  list : ["1", "2"];
}
var myobj1 = new Myobj();
var myobj2 = new Myobj();
myobj1.list.push("3");
alert(myobj2.list); //1,2,3
1.5コンストラクタモードとプロトタイプモードを組み合わせる
ユーザー定義のタイプを作成する最も一般的な方法は、コンストラクタモードとプロトタイプモードを組み合わせて使用し、コンストラクターモードはインスタンス属性を定義するために使用され、プロトタイプは方法と共有の属性を定義するために使用される.各インスタンスは、自分のインスタンス属性のコピーを持っていますが、方法の参照を共有しています.
function Myobj(name) {
  this.name = name;
}
Myobj.prototype = {
  constructor : Myobj;
  getName : function() {
    alert(this.name);
  }
}
1.6ダイナミックプロトタイプモード
動的プロトタイプモードはすべての情報をコンストラクタにカプセル化し,プロトタイプをコンストラクタに初期化することにより,コンストラクタとプロトタイプを同時に使用する利点を維持した.
function Myobj(name) {
  this.name = name;
  if (typeof this.getName != "function") {
    Myobj.prototype.getName = function() {
      alert(this.name);
    }
  }
}
1.7寄生構造関数モード
前のいくつかのモードが適用されていない場合には、寄生構造関数モードを使用することができます.このようなモードの考えは、オブジェクトをパッケージ化するための関数を作成し、新規作成されたオブジェクトに戻ります.
function Myobj(name) {
  var myobj = new Object();
  myobj.name = name;
  myobj.getName = function() {
    alert(this.name);
  }
}
1.8コンストラクタモード
妥当な対象とは、公的な属性がないことを意味し、その方法もthisの対象を引用しないことを意味し、妥当なオブジェクトはいくつかの安全な環境で使用するのに最適である.
function Myobj(name) {
  var myobj = new Object();
  myobj.getName = function() {
    alert(name);
  }
  return myobj;
}
2.継承
2.1プロトタイプチェーン
プロトタイプチェーンの継承を実現するための基本的な考え方は、プロトタイプを利用して他の引用タイプの属性と方法を継承することです.各構成関数にはプロトタイプのオブジェクトがあり、プロトタイプのオブジェクトにはコンストラクタへのポインタが含まれています.例としてはプロトタイプのオブジェクトへのポインタが含まれています.プロトタイプのオブジェクトが他のタイプのインスタンスに等しい場合、プロトタイプのオブジェクトは他のプロトタイプへのポインタを含んでいます.このように累々と進み、実例と原型のチェーンを構成する.いわゆるプロトタイプチェーンである.
function SuperType() {
  this.property = true;
}
SuperType.prototype.getSuperValue = function() {
  return this.property;
}
function SubType() {
  this.subproperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
  return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue());
2.2構築関数を借りる
コンストラクタの基本的な考え方を借りると、サブタイプのコンストラクタの内部で超タイプのコンストラクタを呼び出すことができます.
function SuperType() {
  this.name = "object";
}
function SubType() {
  SuperType.call(this);
}
構造関数を借りる大きな利点は、サブタイプの構造関数で超タイプの構造関数にパラメータを伝えることができることである.
function SuperType(name) {
  this.name = name;
}
function SubType() {
  SuperType.call(this, "object");
}
2.3コンビネーション引継ぎ
組合せ継承も疑似古典継承と呼ばれ、プロトタイプチェーンと借用構造関数の技術を組み合わせた継承パターンを指し、プロトタイプチェーンを使用してプロトタイプの属性と方法の継承を実現するという考えであり、構造関数を利用してインスタンス属性の継承を実現する.
function SuperType(name) {
  this.name = name;
}
SuperType.prototype.getName = function() {
  alert(this.name);
}
function SubType(name) {
  SuperType.call(this, name);
}
SubType.prototype = new SuperType();
2.4原型式継承
プロトタイプによって、既存のオブジェクトに基づいて新しいオブジェクトを作成することができます.
function object(o) {
  function F() {
    F.prototype = o;
    return new F();
  }
}
2.5寄生式引継ぎ
寄生型継承はプロトタイプ継承と密接に関連しており、その構想は寄生構造関数と工場モードと類似している.すなわち、継承プロセスをカプセル化するためだけの関数を作成する.
function createObject(original) {
  var clone = object(original);
  clone.sayHi = function() {
    alert("Hi!");
  }
  return clone;
}
2.6寄生結合式継承
グループ継承の最大の問題は、どのような場合でも、サブタイププロトタイプとサブタイプのコンストラクタ内部を作成する際に、二次超構造関数を呼び出します.寄生結合式継承とは、構造関数を用いて属性を継承し、プロトタイプリンク混成形式で継承する方法である.寄生結合式継承の基本パターンは以下の通りである.
function inheritPrototype(subType, superType) {
  var prototype = object(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}
この記事は「青鋒ノート」のブログから、転載をお断りします.