• ベストアンサー

コンストラクタとプロトタイプについて

ネットで検索したりして調べているのですがいまいちわからなかった箇所が あるので質問させていただきます。 コンストラクタで設定するのとプロトタイプで設定する違いがいまいちわかりません。 例えば function Test { this.prop = hoge; } Test.prototype.prop1 = hogehoge; の場合 コンストラクタのほうが優先されてhogeがでるのはわかるのですが 下記の場合はプロタイプのほうが優先されてhogehogeと出てしまうのは どうしてでしょうか? <script language="javascript"> <!-- //コンストラクタ function Test(){alert("hoge"); } //prototypeでセット Test.prototype=alert("hogehoge"); //オブジェクト作成 var TEST = new Test(); window.onload=TEST; --> </script>

質問者が選んだベストアンサー

  • ベストアンサー
noname#30818
noname#30818
回答No.2

window.onload= function(){ function Test(){ this.prop = 'hoge'; }//関数 Test.prototype.prop1 = 'hogehoge';//これは何か良くわかりません。 alert(Test())//当然undefined function Test1(){ //関数(window.Test1) this.prop = 'hoge';//this(window)にプロパティを追加 return this //(window === this) } Test1().prop1 = 'hogehoge';//戻り値のwindowにプロパティを追加 var cc = '' for(var i in Test1()){ cc += 'Test1().' + i + '=' + Test1()[i] + '<br>' } document.body.innerHTML = cc function Test2(){ this.prop = 'hoge'; }//newで呼ばれているのでコンストラクタ関数 //どの JavaScript 関数もコンストラクタとして使用できます。new 演算子をコンストラクタ関数とともに使用することで新しいオブジェクトを作成します。 //http://developer.mozilla.org/ja/docs/Core_JavaScript_1.5_Guide:Details_of_the_Object_Model#.E3.82.AF.E3.83.A9.E3.82.B9.E3.83.99.E3.83.BC.E3.82.B9.E8.A8.80.E8.AA.9E.E3.81.A8.E3.83.97.E3.83.AD.E3.83.88.E3.82.BF.E3.82.A4.E3.83.97.E3.83.99.E3.83.BC.E3.82.B9.E8.A8.80.E8.AA.9Eより TEST2 = new Test2 //new 演算子に出くわしたので、"新しく汎用オブジェクトを生成"し、この新しいオブジェクトを this キーワードの値としてTest2コンストラクタ関数に渡します。 Test2.prototype.prop1 = 'hogehoge'; //内部的な __proto__ プロパティの値としてTest2.prototypeの値をセットします。 //http://developer.mozilla.org/ja/docs/Core_JavaScript_1.5_Guide:Details_of_the_Object_Model#.E3.82.AF.E3.83.A9.E3.82.B9.E3.83.99.E3.83.BC.E3.82.B9.E8.A8.80.E8.AA.9E.E3.81.A8.E3.83.97.E3.83.AD.E3.83.88.E3.82.BF.E3.82.A4.E3.83.97.E3.83.99.E3.83.BC.E3.82.B9.E8.A8.80.E8.AA.9E //”プロパティの継承”参照 var cc = '<br><br>' for(var i in TEST2){ cc += 'TEST2.' + i + '=' + TEST2[i] + '<br>' } document.body.innerHTML += cc function Test3(){ this.prop = 'hoge'; this.alert = function(){ alert(this.prop) }//メソッド?を追加 } TEST = new Test3 TEST.alert() function Test4(){ this.prop = 'hoge'; } TEST = new Test4 Test4.prototype.alert = function(){ alert(this.prop) }//メソッド?を追加 TEST.alert() //どちらも同じみたいですね。 //だた先ほどのページの”プロパティの追加”を読むと違いが解ると思います。 function Test5(){ this.prop = 'hoge'; } TEST5 = new Test5 Test5.prototype.prop = 'hoge*2' alert(TEST5.prop) //JavaScript がTEST5オブジェクト(Test5のインスタンス)のpropプロパティを探すと、JavaScript はそのプロパティに対するローカル値を発見します。そして Test5.prototypeへのチェーンの検索を停止します。 //ということでTEST5.propは'hoge*2'ではなく'hoge'で良いのだと思いますよ。 }

shoshosho
質問者

お礼

ご回答ありがとうございます。 いろいろ実験していただいて本当にありがとうございました。 試しにTest1を実行しようと思ったのですが 『function Test1(){ //関数(window.Test1)からdocument.body.innerHTML = cc までです。』 なぜか実行しても何も画面にでないのですがこれで正しいのでしょうか? たぶん私の手順が間違っているとは思うのですがいろいろ 試してもなぜか表示できませんでした。

shoshosho
質問者

補足

Test.prototype.prop1 = 'hogehoge' は Test.prototype.prop='hogehoge'の間違いでした。 すいませんでした。

その他の回答 (1)

  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

> //コンストラクタ > function Test(){alert("hoge");} このコンストラクタは"hoge"とアラートを表示する以外に何もしていません。 そのため、 > //オブジェクト作成 > var TEST = new Test(); でTESTには空(プロパティ無し)のオブジェクトが入ります。 (このとき、コンストラクタが実行されることでhogeが表示されます。) > //prototypeでセット > Test.prototype=alert("hogehoge"); ここではalertの戻り値をTest.prototypeにセットしています。 しかし、alertは戻り値を返しませんから、 Test.prototypeはundefinedになるでしょう。 (ここで、alert("hogehoge")は実行されることでhogehogeと表示されます。) # また、prototypeのプロパティではなく # prototype自体に代入することは普通はしないと思います。 > window.onload=TEST; TESTは空オブジェクトなので、onloadでは何も起こりません。 なにかアラートが出ているならこの手前の文がonload前に実行されたことによるものです。

shoshosho
質問者

お礼

ご回答ありがとうございます。 どうやらalertがでているのはonloadによるものではなかった みたいですね・・・。 試しにwindow.onload=TEST;を消してみて実行しましたが ダイアログが出てびっくりしましたが回答者様の解説の おかげでよくわかりました。 解説を見て疑問が沸いたのですが オブジェクト作成時にコンストラクタが実行されるのでしょうか? いまいちまだわかってなくてすいません・・;;

関連するQ&A

  • javascriptのconstructorプロパティについて

    constructorプロパティとは、 オブジェクトの初期化で使用されたコンストラクタ関数を参照 とのことなので、下記2パターンのPGを作成しました 1.prototypeの明記なし function Hoge(){ this.init = "Hogeで初期化"; this.getInit = function(){ return this.init; } } var obj = new Hoge(); alert(obj.constructor == Hoge); for(prop in obj){ alert( prop + " - " + obj[prop]); } //実行結果 True init - Hogeで初期化 getInit - function () { return this.init; } 2.prototypeの明記あり function Hoge(){ this.initialize.apply(this,arguments); this.init = "Hogeで初期化"; this.getInit = function(){ return this.init; } } Hoge.prototype ={ initialize:function(){ this.init = "Hoge.prototype.initializeで初期化"; }, getInit:function(){ return "Hoge.prototype.getInit()"; } } var obj = new Hoge(); alert(obj.constructor == Hoge); for(prop in obj){ alert( prop + " - " + obj[prop]); } //実行結果 false init - Hogeで初期化 getInit - function () { return this.init; } initialize - function () { this.init = "Hoge.prototype.initialize\u3067\u521D\u671F\u5316"; } ・質問内容 prototypeの明記なしの場合は、Hogeのコンストラ関数を参照している(結果がTrueのため) prototypeの明記ありの場合は、falseのためコンストラ関数を参照していないのですが、 prototype明記あり、なしで結果が異なる理由が分からない状態です。 (prototype.constructorにも手を出したのですが、上記が解決しないため  constructorプロパティに関してのみ質問した次第です) ネット、書籍等で調べたのですが、検討がつかない状態です。 お手数ですが、ご教授お願い致します。

  • 【javascript】prototypeを使って宣言したfunctionでthis.の値が取れない

    以下HTMLは開いた時に'aaa'がアラートされるつもりで作りました。 ※行頭は全角スペースです。 <html> <head> <script type="text/javascript"><!-- function hoge(){  this.val ='aaa'; }; hoge.prototype.func = function(){  alert(this.val); }; h = new hoge(); if(window.addEventListener){  window.addEventListener('load', h.func, false); }else{  window.attachEvent('onload', h.func); } //--></script> </head> <body> </body> </html> 結果は、undifindがアラートされました。 alert(this.val); を alert(h.val); とベタに記述すれば回避できますが、ちょっと違和感を感じます。 このような場合、どのような記述がベターなのでしょうか?

  • 下記コードのようなオブジェクトとかprototypeとかを理解するヒントを教えてください!

    <html> <head> <meta charset="utf-8"> </head> <body> <script type="text/javascript"> var hoge = function(){ //▼ function testFunc(n){ } testFunc.prototype.init = function(c){ alert(c); }// end func return{ testFunc:testFunc } }(); var u = new hoge.testFunc(); u.init("あああ"); </script> </body> </html> ---------------------------------------------------- ここ数日いろいろ弄っているのですが、 いまいちピンと来ない感じです。 何か、参考になるようなスクリプトやポイントなどありましたら、 ご紹介いただけると幸いです。 よろしくお願いいたします。

  • prototype.jsを使うとfor~inがバグる件

    下記について知っている人が居ましたら教えてください。 HTAでprototype.jsを使うとfor~inでバグります。 具体的に, prototype.jsを読み込んだ状態でfor~inして, for~inの情報を参照すると,値ではなくソースコードが表示されます。 prototype.jsを読み込ませない場合で,通常のようにfor~inして, for~inの情報を参照すると,問題なく値が参照できます。 OS環境とバージョンによって違うかもしれませんが,僕の環境では現象が発生します。 対策方法を知っている人がいましたら教えてください。 下記のソースを実行すると, バグらない場合は,次のように出力されます。 hoge piyo toge バグる場合は,次のように出力されます。 function(item, i) { i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; var n = this.slice(0, i).reverse().indexOf(item); return (n < 0) ? n : i - n - 1; } -略- { this._each(function(value) { iterator(value, index++); }); } catch (e) { if (e != $break) throw e; } return this; } hoge piyo toge prototype.js使用すると... ///////////////////////////////////// // sample.hta バグ <html> <head> <title>ツール</title> <script type="text/javascript" src="./prototype.js"></script> </head> <body onLoad="javascript:window.resizeTo(600,480)"> <script language="javascript"> {   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } </script> </body> </html> prototype.js使用しないと... ///////////////////////////////////// // sample.hta バグらない <html> <head> <title>ツール</title> <!-- <script type="text/javascript" src="./prototype.js"></script> --> </head> <body onLoad="javascript:window.resizeTo(600,480)"> <script language="javascript"> {   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } </script> </body> </html> prototype.jsを最後に読み込ませると... ///////////////////////////////////// // sample.hta バグらない <html> <head> <title>ツール</title> </head> <body onLoad="javascript:window.resizeTo(600,480)"> <script language="javascript"> {   // Iniイメージ   // [TEST]   // KEY1=hoge   // KEY2=piyo   // KEY3=toge   var section = "TEST";   var key = new Array("KYE1", "KYE2", "KYE3");   var data = new Array("hoge", "piyo", "toge");   // セクション   items = new Array();   items[ section ] = new Array();   // キー   for(var i=0;i<key.length;i++){     items[ section ][ key[i] ] = data[i];   }   // 参照   for(var j in items[ section ]){     document.write( items[ section ][ j ] + "<br />\n" );   }   delete key;   delete data;   delete items; } </script> <script type="text/javascript" src="./prototype.js"></script> </body> </html>

  • prototype.jsにて

    hoge = Class.create(); hoge.prototype = { 省略.... } hogehoge = new Test(); Testクラスの中で、 「hogehoge」というインスタンス名を取得することは可能でしょうか?

  • コンストラクタすると同時にメソッドをオーバーロードするには?

    コンストラクタすると同時にメソッドをオーバーロードするには? リスナー関数でthisの参照先が変わってしまう問題に悩んでいます。 <!-- 方法(1) コンストラクタした後にメソッドを上書きする --> <p id="Test">test</p> <script type="text/javascript"><!-- function Hello (value){ this.value = value ? value : 'Hello, World!'; } Hello.prototype.start = function (event) { alert(this.value); } var world = new Hello(); var start = function (event) { world.start.call(world, event); }; // thisがworldを参照するようにstartメソッドを作り直す document.getElementById('Test').addEventListener('click', start, false); //--></script> 上記コードは期待通りの動作ですが、せっかくコンストラクタしたにも関わらず、メソッドを上書きしなくてはなりません。 コンストラクタした時点でstartメソッドが完成しているのが理想です。 (以下、全角空白は半角空白に置換してください) <!-- 方法(2) クロージャでメソッドを生成する --> <p id="Test">test</p> <script type="text/javascript"><!-- function Hello (value) {  function start (event) {   alert(this.value);  }  this.value = value ? value : 'Hello, World!';  this.start = (function(that){   return function (event) {    start.call(that, event);    that = null;   };  })(this); } var world = new Hello('Hello, World2!'); document.getElementById('Test').addEventListener('click', world.start, false); //--></script> こちらは完全に期待通りの動作を示しますが、prototype を使用していないのが少し気になります。 <!-- 方法(3) クロージャで prototype.start を上書きする --> <p id="Test">test</p> <script type="text/javascript"><!-- function Hello (value) {  this.value = value ? value : 'Hello, World!';  this.start = (function(that, start){   return function (event) {    start.call(that, event);    that = start = null;   };  })(this, this.start); } Hello.prototype.start = function start (event) {  alert(this.value); }; var world = new Hello('Hello, World2!'); document.getElementById('Test').addEventListener('click', world.start, false); //--></script> 結果としては期待通りのコードになったのですが、以下の点が気になっています。 ・方法(2)、方法(3) を比較すると、それぞれどのようなメリット、デメリットがあるのか。(prototypeが高速と聞いてからは (3) に傾いているのですが、よくわかっていません) ・コンストラクタ時に発動する特別なメソッド、プロパティが用意されているのか。 ・クロージャを使わずに解決できるのか。 ・全く別の方法(もっと良い実装)があるのか。 コードの書き方は千差万別だとは思いますが、主観で結構ですので、アドバイスいただければ幸いです。 # start() はサンプル故に短いコードですが、実際には比較的長いコードがある状態を想定しています。

  • <body onload=""> と window.onload

    JavaScriptのonload処理についての質問です。 現在Java、JSP、JavaScript等でWebアプリケーションを作成しているのですが、 bodyタグ中のonloadに記載したファンクションが時々呼ばれないという問題が起きています。 (こんな感じで記述  <body onload="hoge();hogehoge();">  hogehoge()がたまに呼ばれないことがある・・・) これを回避する方法として、「onload処理をwindow.onloadに記述すれば良い」 という話を聞きました。 (こんな感じで記述  <script>    window.onload = function(){ hoge();hogehoge(); }  </script> ) 「bodyタグ中に記述するとたまに呼ばれないものが、window.onloadに記述すると確実に呼ばれる」 なんてことがあるのでしょうか? 「2つめのファンクションが呼ばれない」という現象がたまにしか発生しないので、 window.onloadに記述する方法で確実に呼ばれるようになったという保証がとれません。 知識として知っている方がいれば是非教えていただきたいです。 よろしくお願い致します。 ※ブラウザはIEを使用  バージョンは IE → 6.0      JavaScript → 1.1 です。  

  • prototype の使い方

    prototype プロパティについて勉強しているのですが、次のような使い方で正しいのでしょうか。 var Dog = function() { this.sit = "I am sitting."; } var myDog = new Dog(); alert(myDog.sit); //“I am sitting.”と表示される。 var Dog2 = function() {} Dog2.prototype.sit = new Dog().sit; var myDog2 = new Dog2(); alert(myDog2.sit); //“I am sitting.”と表示される。 prototype の行で new Dog() を作るとゴミが出る気がするのですが、勝手に解放されるのでしょうか。

  • Javascriptの関数について

    Internet Explorer の右クリックメニューに登録するスクリプトを作っています。 たとえば、いま表示しているページのURLを表示する場合、 <script type="text/javascript"> var parentWindow = window.menuArguments; var URL = parentWindow.document.URL; window.onload = function() {   kansuu(URL); }; kansuu = function(url) {   alert(url); } </script> ↑は動きます。 また、 var parentWindow = window.menuArguments; var URL = parentWindow.document.URL; window.onload = kansuu(URL); function kansuu(url) {   alert(url); } ↑も動きます。 ところが、 var parentWindow = window.menuArguments; var URL = parentWindow.document.URL; window.onload = kansuu(URL); kansuu = function(url) {   alert(url); } は動きません。 なぜでしょうか? 理由を教えていただけると嬉しいです。 よろしくお願いします。

  • イベントハンドラに処理を追加するには?

    例えばbodyタグのonloadイベントハンドラに JavaScriptを使って処理を追加するにはどうすればよいのでしょうか? 例) ・rei.htm <html>  <script language="JavaScript" type="text/javascript">  function hoge(){   alert("hogeです");  }  function foo(){   alert("fooです");  }  </script>  <body onload="hoge();">  </body>  <script language="JavaScript" type="text/javascript">  document.body.onload += foo();  </script> <html> ※前提条件として、変更可能な箇所はscriptタグ内のみとなります。 「こんなんでいけないかな?」と思って上記のようにやってみたのですがうまくいきませんでした。 (結果はfoo()のみ実行され、hoge()は実行されませんでした。 alertでbody.onloadの中身を確認すると『function anonymous{hoge();}undefined』と表示されるので、なぜfoo()が実行されてhoge()が実行されないのかよくわかりませんが‥) また試しに document.body.onload += foo(); これを以下のように変更してみました。 document.body.onload = foo(); この時は、 ・foo()の実行  ↓ ・javascriptエラー  ↓ ・hoge()の実行 となりました。(これもなぜこうなるのかよくわかりせん) 以上、イベントハンドラに最初から任意に入れられている処理を残しつつ、 さらに処理を加えるにはどうすればよいのかご教示お願いします。