2009-11-09 9 views
7

誰かがOOのjavascriptでfunction.prototypeのthingie(thingie !! ??)を説明するのに十分親切かもしれないのだろうかと思います。次のコードスニペットを考える誰かがjavascriptのプロトタイプの継承を説明することができます

私は、サーバーサイドのプログラミングの背景から来て、私はプロトタイプの全体のコンセプトを把握するわけではないかもしれ、

var animate=function(){}; 
animate.angular=function(){/*does something here*/}; 
animate.circular=function(){/*does something here*/}; 

そして

var animate=function(){}; 
animate.prototype.angular=function(){/*does something here*/}; 
animate.prototype.circular=function(){/*does something here*/}; 

私が言うことができる限り、後者の関数はanimate.angular(/*args*/)animate.circular(/*args*/)でコールできるので、私の質問は、第2の方法で関数を定義することは?どのように、なぜそれらが異なるのですか?

希望私は意味を成していた...

EDIT:啓発答えてありがとうすべて、それが「正しい」ものとして、ここで答えを判断するのは非常に難しいので、私は私が感じる1つもりマークです最も貢献...あなたのすべては確かに私の思考のためのより多くの食料を与えている

を作った...

+3

プロトタイプ継承(特にwrt JavaScript)について説明するもう一つの大きな答え:http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript/1598077#1598077 –

+2

も参照してください。http://stackoverflow.com/questions/186244/what-does-it-mean-that-javascript-is-a-prototype-based-language –

答えて

6

私はあなたが)(あなたの例ではどこかを新しいアニメーションと同じものを設定するためのものだと思います。 新しいを使用せずに、私は何が起こるかについて少し詳しく説明します:

var animate = function(){ console.log(0, 'animate'); }; 
animate.angular = function(){ console.log(1, 'animate.angular'); }; 
animate.circular = function(){ console.log(2, 'animate.circular'); }; 

animate.prototype.angular = function(){ console.log(3, 'animate.prototype.angular'); }; 
animate.prototype.circular = function(){ console.log(4, 'animate.prototype.circular'); }; 

最初の2つの機能、#1 &#2を、アニメーション変数から呼び出し可能です。

animate.angular(); 
animate.circular(); 

あなたは新しいアニメーションを作成する場合は()あなたは次の2、#3 &#4、(ただし、#1または#2)を呼び出すことができます。

var ani2 = new animate(); 

ani2.angular(); 
ani2.circular(); 

また、animate()は関数ですが、ani2はありません。

console.log(5, typeof animate); 
console.log(6, typeof ani2); 
console.log(7, animate()); 

ani2はすでに作成されていますが、animate.prototypeを使用して新しいメンバーを追加できます。

animate.prototype.bark = function(){ console.log(8, 'bark'); }; 
ani2.bark(); 

animate変数はプロトタイプを継承しませんが、

console.log(9, typeof ani2.bark); 
console.log(10, typeof animate.bark); 

アニメーション変数に直接適用されたメンバーを継承しないことに注意してください。 animate.prototypeからのみ継承します。

animate.paperclip = function(){ console.log(11, "paperclip"); }; 

animate.paperclip(); 
console.log(12, typeof ani2.paperclip); 
console.log(13, typeof animate.paperclip); 

また新しい子供たちにインスタンスメンバーを追加するには、アニメーションのようなコンストラクタ関数内このキーワードを使用することができます。

var Anime = function(a,b){ this.a=a; this.b=b; this.c=console; }; 
var anime1 = new Anime(14, 'anime1'); 
var anime2 = new Anime(15, 'anime2'); 
anime1.c.log(anime1.a, anime1.b); 
anime2.c.log(anime2.a, anime2.b); 

Anime.prototype.a = 16; 
Anime.prototype.z = 'z'; 

var anime3 = new Anime(17, 'anime3'); 
anime3.c.log(18, anime3.a, anime3.b, anime3.z, " ", anime2.a, anime2.b, anime2.z, " ", anime1.a, anime1.b, anime1.z); 
anime2.z='N'; 
anime3.c.log(19, anime3.a, anime3.b, anime3.z, " ", anime2.a, anime2.b, anime2.z, " ", anime1.a, anime1.b, anime1.z); 

メモリは自動的にそれが変更されたという理由だけでanime2.zの別のインスタンスのために割り当てられ、anime1 & anime3依然として「共有」倹約未修飾Zました。

a、b、およびcのメンバーは、同じ方法で「共同」ではありません。これらは、コンストラクタですぐに割り当てられました。new Anime()(Anime.prototypeから継承されません)。また、プロトタイプ上のaメンバは常にコンストラクタによって「個別化」されます。

新しいキーワードを忘れたり、そうでないようにする必要はありません。例えば、このは、という新しいなしで呼ばれるコンストラクタ内のグローバルオブジェクトを指します。

console.log(20, typeof window.a, typeof window.b, typeof window.c); 
var opps = Anime(21, 'zapp'); 
console.log(22, typeof window.a, typeof window.b, typeof window.c); 
console.log(23, typeof opps); 

ここに出力があります。トムがダグラス・クロックフォードのビデオを提案してくれたのは2番目です!


/* 
1 animate.angular 
2 animate.circular 
0 animate 
3 animate.prototype.angular 
4 animate.prototype.circular 
5 function 
6 object 
0 animate 
7 undefined 
8 bark 
9 function 
10 undefined 
11 paperclip 
12 undefined 
13 function 
14 anime1 
15 anime2 
18 17 anime3 z 15 anime2 z 14 anime1 z 
19 17 anime3 z 15 anime2 N 14 anime1 z 
20 undefined undefined undefined 
22 number string object 
23 undefined 
*/ 
+0

あなたがよく使っているコンベンションでは、新しいキーワードを忘れないようにするコンストラクタ関数の大文字の最初の文字を使うことです。プロトタイプの継承に関する優れた記事は、次のサイトを参照してください。http://msdn.microsoft.com/en-us/magazine/ff852808.aspx –

2

Javascriptが非常に強力ですが、すべてのことを強く他の言語に比べて構造ではない...奇妙な言語です。.. 。

プロトタイプは、クラスの複数のインスタンスを作成する場合、JavaScriptがメモリを節約する方法です...したがって、OOPの方法でJSを使用している場合は、プロトタイプの一部として関数を定義する必要があります。また、プロトタイプを使用して継承をシミュレートする方法もあります。

このことについて多くの素晴らしい説明をするには、書籍"Javascript, the Good Parts"を強くお勧めします。

+0

Google Tech Talk of the同じ名前:http://www.youtube.com/watch?v=hQVTIJBZook 今日はちょうどそれを見ました。 –

+1

@ gunderson:「奇妙な」は非常に主観的な表現です。 JSを6ヶ月間正しく学習した後、私は自分がJavaやC++を使用しているよりも、より流暢かつ自然にプログラミングすることができます。したがって、私はあなたに同意することはできません。 –

+0

これは私がmootoolsが大好きな理由、それは私が感謝するスタイルでJavaScriptの継承を公開しています。 –

2

3時間の余裕があれば、YUIシアターの "The JavaScript Programming Language"ビデオをご覧になることをお勧めします。スピーカー/先生はDouglas Crockfordです。彼はあなたにあなたが構築することができる確固たるJS基盤を提供します。

よろしく

トム

3

それは時々そのように感じているにもかかわらず、Javascriptをクラスを持っていますが、プロトタイプで動作しません。プロトタイプを定義したら、そのプロトタイプのコピーを作成できます。

を皮切り:

var animate=function(){}; 
animate.angular=function(){/*does something here*/}; 

次のことができます。

var a = new animate(); 
animate.angular();  // OK 
a.circular();   // error: a.circular is not a function 

しかし、あなたが起動している場合:今

function animate(i){}; 
animate.prototype.angular = function() {}; 

することができます

var a = new animate(); 
a.angular(); 

もちろん、インスタンス変数があればこれはもっと面白いです。

function animate(i) { 
    this.x = i; 
} 
animate.prototype.angular = function() { 
    this.x *= 2; 
} 

var a = new animate(5); 
a.angular(); 
console.log(a.x); // 10 
2

プロトタイプベースのOOPはあなたに自由を与えます。Classy OOPではありません。

多くの人が言っているように、それについて学ぶためには、Crockfordの説明を読んで、それ以上のリソースを得ることはできません。

クイック恩恵をしたい場合はこのような(クラスは他の言語であるかを表します)オブジェクトを定義

var Building = function() { 
    this.openDoor = function() {}; 
}; 

var House = function() { 
    this.closeDoor = function() {}; 
}; 
House.prototype = new Building(); 

var a = new House(); 
a.openDoor(); 
a.closeDoor(); 

があまりにも嫌なので、私は私の答えに少し先端が含まれます:

をお使いのシステムを構築するための

最善の方法は、例えば、あなたが選択したグローバル名前空間の下にある:

if (typeof MYAPP === 'undefined' || !MYAPP) { 
    var MYAPP = {}; 
} 

function New(className, classBody) { 
    // This adds your "classes" to this MYAPP namespace so they can be instantiated 
    // You need some magic here, so have fun with this function 
} 

New('Building', function() { 
    this.openDoor = function() {}; 
}); 

New('House', function() { 
    this.prototype = new MYAPP.Building(); 
    this.closeDoor = function() {}; 
}); 

// Now you can do the same as before but your application is cleaner :) 
var a = new MYAPP.House(); 
a.openDoor(); 
a.closeDoor(); 

乾杯。

関連する問題