他のほとんどのオブジェクト指向言語とは異なり、JavaScript には実際にはクラスの概念がありません。他のほとんどのオブジェクト指向言語では、特定のクラスのインスタンスをインスタンス化しますが、JavaScript ではそうではありません。
JavaScript では、オブジェクトは新しいオブジェクトを作成でき、オブジェクトは他のオブジェクトから継承できます。
この概念全体をプロトタイプ継承と呼びます。
しかし、どうやってオブジェクトを作ることができるでしょうか?
で汎用オブジェクトを作成するだけです{}
。
var a = {};
a.prop = "myprop";
console.log(a); //Object { prop="myprop" }
関数ではないため、のインスタンスを作成できませんa
。つまり、特別な内部メソッドはありません[[Construct]]
。
JavaScript では、任意の関数をオブジェクトとしてインスタンス化することもできます。以下の関数は、名前を取り、それを現在のコンテキストに保存する単純な関数です。
function User( name ) {
this.name = name;
}
User
それがFunction のインスタンスであることがわかります:
alert(User instanceof Function); //true
指定された名前で、その関数の新しいインスタンスを作成します。
var me = new User( "My Name" );
name
それ自体のプロパティとして設定されていることがわかります。
alert( me.name == "My Name" ); //true
そして、それがUser
オブジェクトのインスタンスであること:
alert( me.constructor == User ); //true
さて、User()
は単なる関数なので、そのように扱うとどうなるでしょうか?
User( "Test" );
this
コンテキストが設定されていないため、デフォルトでグローバルオブジェクトwindow
になります。つまり、提供されたものwindow.name
と同じです。name
alert( window.name == "Test" ); //true
プロパティはすべてのconstructor
オブジェクトに存在し、それを作成した関数を常に指します。このようにして、オブジェクトを効果的に複製し、同じ基本クラスの新しいオブジェクトを作成できますが、同じプロパティは使用できません。この例を以下に示します。
var you = new me.constructor();
実際、コンストラクターは同じであることがわかります。
alert( me.constructor == you.constructor ); //true
プロトタイプと公開メソッド
プロトタイプには、親オブジェクトのすべての新しいコピーの基本参照として機能するオブジェクトが含まれているだけです。基本的に、プロトタイプのすべてのプロパティは、そのオブジェクトのすべてのインスタンスで使用できます。この作成/参照プロセスにより、継承の安価なバージョンが得られます。
オブジェクト プロトタイプは単なるオブジェクトであるため、他のオブジェクトと同様に、新しいプロパティを追加できます。新しいプロパティをプロトタイプにアタッチすると、元のプロトタイプからインスタンス化されたすべてのオブジェクトの一部になり、すべてのプロパティが効果的に公開されます。例:
function User( name, age ){
this.name = name;
this.age = age;
}
メソッドとプロパティをコンストラクター関数のプロトタイプ プロパティに追加することは、このコンストラクターが生成するオブジェクトに機能を追加するもう 1 つの方法です。CardNo
もう 1 つのプロパティとgetName()
メソッドを追加しましょう。
User.prototype.CardNo='12345';
User.prototype.getName = function(){
return this.name;
};
そして、プロトタイプに別の関数を追加します。コンテキストがインスタンス化されたオブジェクト内にあることに注意してください。
User.prototype.getAge = function(){
return this.age;
};
新しいユーザー オブジェクトをインスタンス化します。
var user = new User( "Bob", 44 );
アタッチした 2 つのメソッドが適切なコンテキストでオブジェクトに関連付けられていることがわかります。
alert( user.getName() == "Bob" ); //true
alert( user.getAge() == 44 ); //true
したがって、JavaScript のすべての関数にはプロトタイプ プロパティがあります。その初期値は空のオブジェクト ({}) です。一般的なオブジェクト (関数ではない) にはプロトタイプ プロパティがないことに注意してください。
alert( user.prototype ); //undefined (and it is not useful even you define it)
委任
のプロパティにアクセスしようとするuser
とuser.name
、JavaScript エンジンはオブジェクトのすべてのプロパティを調べて呼び出されたものを探し、name
見つかった場合はその値を返します。
alert( user.name );
JavaScript エンジンがプロパティを見つけられない場合はどうなりますか? このオブジェクトを作成するために使用されるコンストラクター関数のプロトタイプを識別します (そうする場合と同じですuser.constructor.prototype
)。プロパティがプロトタイプで見つかった場合、このプロパティが使用されます。
alert(user.CardNo); // "12345"
など...
オブジェクト自身のプロパティとプロトタイプのプロパティを区別したい場合は、 を使用しますhasOwnProperty()
。試す:
alert( user.hasOwnProperty('name') ); //true
alert( user.hasOwnProperty('CardNo') ); //false
プライベート メソッド
関数のプロパティを直接設定すると、プライベートになります。例:
function User()
{
var prop="myprop";
function disp(){
alert("this is a private function!");
}
}
var we = new User();
alert(we.prop); //undefined
we.disp(); // Fails, as disp is not a public property of the object
特権メソッド
特権メソッドはDouglas Crockfordによって造られた用語で、(オブジェクト内の) プライベート変数を表示および操作できる一方で、パブリック メソッドとしてユーザーがアクセスできるメソッドを指します。例:
新しいユーザー オブジェクト コンストラクターを作成します。
function User( name, age ) {
//Attempt to figure out the year that the user was born:
var year = (new Date()).getFullYear() – age;
//Create a new Privileged method that has access to the year variable, but is still publically available:
this.getYearBorn = function(){
return year;
};
}
ユーザー オブジェクトの新しいインスタンスを作成します。
var user = new User( "Bob", 44 );
返された年が正しいことを確認します。
alert( user.getYearBorn() == 1962 ); //true
また、オブジェクトのプライベート year プロパティにアクセスできないことに注意してください。
alert( user.year == null ); //true
基本的に、特権メソッドは動的に生成されるメソッドです。これは、コードが最初にコンパイルされたときではなく、実行時にオブジェクトに追加されるためです。この手法は、単純なメソッドをオブジェクト プロトタイプにバインドするよりも計算コストが高くなりますが、はるかに強力で柔軟です。
静的メソッド
静的メソッドの背後にある前提は、他の通常の関数の前提と実質的に同じです。ただし、主な違いは、関数がオブジェクトの静的プロパティとして存在することです。プロパティとして、そのオブジェクトのインスタンスのコンテキスト内ではアクセスできません。これらは、メイン オブジェクト自体と同じコンテキストでのみ使用できます。従来のクラスのような継承に慣れている人にとって、これは静的クラス メソッドのようなものです。
実際には、この方法でコードを記述することの唯一の利点は、オブジェクトの名前空間をきれいに保つことです。
User オブジェクトにアタッチされた静的メソッド:
function User(){}
User.cloneUser = function( user ) {
//Create, and return, a new user
return new User( user.getName(), user.getAge() );
};
このcloneUser
機能には、次のユーザーのみがアクセスできますUser
:
var me = new User();
me.cloneUser(me); //Uncaught TypeError: Object #<User> has no method 'cloneUser'