• ベストアンサー

コンストラクタと静的メソッドを簡単に定義する

立て続けに質問することをお許し下さい。。 以下のようなPersonクラスがあるとします。 /**** Person クラス(全角スペース表記) ****/ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <HTML>  <HEAD>   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">   <META HTTP-EQUIV="Content-Script-Type" CONTENT="javascript">   <TITLE>教えて!gao</TITLE>   <SCRIPT TYPE="text/javascript">    function Person(name, age, sex, color) {     this.name = name;     this.age = age;     this.sex = sex;     this.color = color;    }    Person.prototype = {     name:null,     age:null,     sex:null,     color:null    };    Person.YELLOW = "黄色人種";    Person.BLACK = "黒色人種";    Person.WHITE = "白色人種";    function test() {     var person = new Person("ggaogg", 23, "male", Person.YELLOW);     var resultBlock = document.getElementById("resultBlock");     for (property in person) {      resultBlock.appendChild(document.createTextNode(property + " = " + person[property]));      resultBlock.appendChild(document.createElement("BR"));     }    }   </SCRIPT>  </HEAD>  <BODY ONLOAD="test()">   <DIV ID="resultBlock"></DIV>  </BODY> </HTML> /********************************************************/ これの実行結果は、以下の通りです。 name = ggaogg age = 23 sex = male color = 黄色人種 しかし、静的変数を、毎回「Person.」を付けて記述するのは面倒で、すべて{}でひとくくりになっていたほうが可読性も増すと思い、以下のようにできると思いましたが、そうしたところ new Person("ggaogg", 23, "male", Person.YELLOW); の部分がコンストラクタではないというようなエラーとなってしまいます。(Web等でこの書き方はあまり見かけないが自分は気に入っている) /************ 変更した部分 ******************/ Person = { YELLOW : "黄色人種", BLACK : "黒色人種", WHITE : "白色人種" }; /********************************************/ 多分、初めに行ったコンストラクタの定義とこの{}の定義とが競合しているためだと思うのですが、何かよい書き方ありませんでしょうか。

  • ggaogg
  • お礼率86% (209/243)

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

  • ベストアンサー
  • arexis
  • ベストアンサー率66% (66/99)
回答No.3

あ、質問がなんとなくわかりましたが、説明が難しい。 /* 書換え前 */ Person.YELLOW = "黄色人種"; Person.BLACK = "黒色人種"; Person.WHITE = "白色人種"; の部分だけを /* 書換え後 */ Person = { YELLOW : "黄色人種", BLACK : "黒色人種", WHITE : "白色人種" }; と単に簡略化したいと言う事でしょうか? 書換え後の方法でPersonに後から追加してるつもりなら、 この書き方では『追加』にならずに新たな Person 変数(オブジェクト)を定義してるだけ。 同じ名前を持つ コンストラクタ function Person(){} がこの時点で消滅します。 また、prototypeで追加の形をとれば、それらはコンストラクタとして呼ばれた時に全てを生成してしまいます。 そもそも書換え前の時点でも Personをコンストラクタとして用意しながら、 オブジェクトとして別利用(間借りしてるような物)してるので、それ自体が目的とする意図ともしかしたらずれてるかもしれないと思います。 コンストラクタとなる function Person の中で #2の方法などで this.colorを定義する時に 引数colorの値に応じて動的に定義させるか、 colorに渡す引数を別の場所でオブジェクトとして定義しておきたいなら、 col = { YELLOW : "黄色人種", BLACK : "黒色人種", WHITE : "白色人種" }; var person = new Person("ggaogg", 23, "male", col.YELLOW); の様に Personではなく、別の名前にすれば普通に成り立ちます。 ちょっと考えすぎて迷路に入ってませんか? ^^;

ggaogg
質問者

お礼

>と単に簡略化したいと言う事でしょうか? そうそう、そうなんです。 長くJavaのスタイルに慣れてしまったせいで、現在JavaScriptの書き方に当惑中です。。 #2の方法ですが、ハッシュを一時的に作成して、そこから値を取り出すということが、#3を読んでようやく分かりました。 残念ながら#2は今回求めていた答えそのものではなかったですが、こんな書き方も面白いですね。 定数だけ別のクラスに定義する方法は、無難ではありますね。 そもそもC言語とかだと名前空間も何もないところにdefineしているわけですし、Cの後にJavaを学習したときにも、「クラスの外に定数宣言できないかな・・」と考えていたことを思い出しました・・。 というわけで、なんだか色々と考えて頂いちゃったみたいですけど、JavaScriptの流儀でやろうと思います。 言語仕様で簡単に素直に実現することが難しいということが分かっただけでも収穫でした。 どうもありがとうございました。

その他の回答 (2)

  • arexis
  • ベストアンサー率66% (66/99)
回答No.2

質問者さんの作ろうとしてる物と意図が同じになるかわかりませんが function Person(name, age, sex, color) { this.name = name; this.age = age; this.sex = sex; this.color = {YELLOW:"黄色人種",BLACK:"黒色人種",WHITE:"白色人種"}[color]; } function test() { var person = new Person("ggaogg", 23, "male", 'YELLOW'); var resultBlock = document.getElementById("resultBlock"); for (property in person) { resultBlock.appendChild(document.createTextNode(property + " = " + person[property])); resultBlock.appendChild(document.createElement("BR")); } } これで事が足りるでしょうか?

  • ai10
  • ベストアンサー率27% (3/11)
回答No.1

私が知っている限りでは withでしょうか…あまりオススメしませんが with( Person ) {   YELLOW = "";   BLACK = "";   WHITE = ""; } これでいけると思います。多分…。

ggaogg
質問者

お礼

先ほどの質問に続き、ありがとうございます。 調べてみると、javascript1.2で導入されたようですね。 こちらの環境では、Person.YELLOW、Person.BLACK、Person.WHITEは、いずれもundefinedになりました(IE7とFireFox2.0.0.12)。 さらに、ai10さんがおっしゃられるように、現在非推奨であるとの記述が多々あったので、これを使うのは避けようと思います。 しかし情報が見つからなかっただけでなく、実際にJavaScriptを使われている方でも使わない記述となると、私の求めるものはなんだか邪道に思えてきました。

関連するQ&A

  • 静的メソッドとインスタンスメソッドを定義する方法

    簡単な、カウンタクラスからのインスタンス作成とその利用のテストを行いました。 テストとして作成した以下の内容のファイルをブラウザ(IEやFireFox)で開くと、期待した結果は返りますが、(Windowsで処理待ちを示す)砂時計マークがいつまで経っても消えません。 どこかで永続ループでもしているのでしょうか。 どこに問題があるのか、また、こういった問題のデバッグのコツを教えて下さい。 よろしくお願いします。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <HTML> <HEAD> <TITLE>教えて!goo</TITLE> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> <META HTTP-EQUIV="Content-Script-Type" CONTENT="javascript"> <SCRIPT TYPE="text/javascript"> function Counter(initialCount) { this.count = initialCount; } Counter.prototype = { count : 0, increment : function() { this.count += 1; }, decrement : function() { this.count -= 1; } } Counter.newInstance = function(initialCount) { return new Counter(initialCount); } var counter; function testCounter() { counter = Counter.newInstance(100); counter.increment(); document.write(counter.count); } </SCRIPT> </HEAD> <BODY ONLOAD="testCounter()"> </BODY> </HTML>

  • DOMで生成したタグにCSSが適用されない(IE)

    DOMでタグを生成した場合、IEではそのタグにCSSが適用されないのですが 何かいい解決法はないでしょうか。ちなみに試したHTMLは下記の通りです。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>test</title> </head> <body> <script type="text/javascript"><!-- A = document.createElement("div"); A.setAttribute("id", "A"); A.setAttribute("style", "color:red;"); document.body.appendChild(A); document.getElementById("A").appendChild(document.createTextNode("test")); --></script> </body> </html>

  • JavaScripでラベル名を取得したい

    い。 以下に記述しているHTMLとJavaScriptでは valueの値、red, blue, yellowしか取得できません。 HTMLからvalue属性を外すと”on”しか出てきません。 このようなHTMLが記述されている場合、どうすればラベル名(赤、青、黄)を取得できますか? 分かる方いらっしゃいましたら教えて下さい。 宜しくお願いします。 (HTML)   <input type="radio" name="color" value="red">赤 <input type="radio" name="color" value="blue">青 <input type="radio" name="color" value="yellow">黄 <button>Add!</button> <ul> </ul> ------------------------------------- (JS) 'use strict'; { document.querySelector('button').addEventListener('click', () => { const colors = document.querySelectorAll('input'); let selectedColor; colors.forEach(color => { if (color.checked === true) { selectedColor = color.value; } }); const li = document.createElement('li'); li.textContent = selectedColor; document.querySelector('ul').appendChild(li); }); }

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

    コンストラクタすると同時にメソッドをオーバーロードするには? リスナー関数で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() はサンプル故に短いコードですが、実際には比較的長いコードがある状態を想定しています。

  • callについて

    http://www.tohoho-web.com/js/object.htm#inheritClass function Person2(name, age, email) { this.email = email; Person.call(this, name, age); } ここのHPにあるこの文にcallが使われていますが thisはPerson関数をさしているのでしょうか? 一番目の引数にある関数に、残りの引数を渡すと思っているのですが thisのところにnullがある場合はどうなるのでしょうか? (他のスクリプトですがcall(null ,hoge,hoge)という使われ方をしているのを見ました) またnullの場合とthisの場合の違いも教えていただけると嬉しいです。 できる範囲でいいので解説お願いいたします。 質問の意味がわからず補足が必要な場合は遠慮なく補足要求してください。

  • C言語 家系図

    問題 構造体personを以下のように仮定する。 struct person { int age; char name[20]; struct person *father; struct person *mother; }; この構造体の表す人の名前、年齢、その人の父親の名前、およびその人の母親の名前を出力する関数 void print_person(struct person *p) を作成せよ。出力の形式は name: 本人の名前 age: 本人の年齢 father: 父親の名前 mother: 母親の名前 となるようにすること。 また、ポインタ father や mother の値が NULL のときには、名前のかわりに unknown と出力するようにせよ。 以上が問題なのですが自分でプログラムを作ってみたところ実行したら、エラーになって矯正終了されてしまいました。 以下が私の作ったプログラムです。 #include <stdio.h> struct person { int age; char name[20]; struct person *father; struct person *mother; }; void set_name(struct person *p, char name[]) { int i; i = 0; while (name[i] != 0) { p->name[i] = name[i]; i++; } p->name[i] = 0; } void print_person(struct person *p) { printf("name:%s", p->name); printf("age:%s\n",p->age); if(p->father != NULL){ printf("father:%s\n",p->father); } else{ printf("unknown"); } if(p->mother != NULL){ printf("mother:%s\n",p->mother); } else{ printf("unknown"); } } int main(void) { struct person me, dad, mom; set_name(&me, "Michael"); me.age = 16; me.father = &dad; me.mother = &mom; set_name(&dad, "David"); dad.age = 38; dad.father = NULL; dad.mother = NULL; set_name(&mom, "Susan"); mom.age = 36; mom.father = NULL; mom.mother = NULL; print_person(&me); print_person(&dad); print_person(&mom); return (0); } どこが違うのか教えていただけないでしょうか?

  • Javascriptの書き方

    素朴な質問なんですが、 JavaScriptを書くとき、全部左寄せにそろえて 良いのでしょうか? 下のように、段差があったほうがいいのでしょうか? function toStringOfPerson() { return (this.name + " / " + this.age); } function Person(name, age) { this.name = name; this.age = age; this.toString = toStringOfPerson; } ホームページを作成中、 半角スペースが2つ、3つ重なったところを 一括変換していて、疑問がわきました。

  • オブジェクトが存在しない

    というエラーが次のhtmlファイルをブラウザで表示させようとするとでます if(document.form0.title!=null) で判断しているだけでだめみたいです そしたらdocument.form0.titleが存在するかどうかをエラーなしで判断させる方法はあるのでしょうか? <HTML> <HEAD> <script type='text/javascript'> <!-- function FormFocus() {  if(document.form0.title!=null)document.form0.title.focus(); } // --> </script> </HEAD> <body onload='javascript:FormFocus()'> <form name='form0'></form> </BODY> </HTML>

  • thisとvar ?

    javascript初心者です。 コンストラクタ(プロトタイプ)とクロージャを学んでいますが、 コンストラクタ(プロトタイプ)では、関数内にthisで変数宣言、クロージャはvarで宣言しています。 この違いの理由は何でしょうか?漠然とした質問ですみません。 thisとvarでの変数宣言の違いなど教えていただけないでしょうか? コンストラクタ-------------------- function Person(n){ this.name = n; } Person.prototype.city = 'Tokyo'; Person.prototype.moveTo = function(c){ document.write(this.name + ': Moving to... ' + c + '<br>'); Person.prototype.city = c; } クロージャ------------------- function Person(n, a){ var name = n; var age = a; return { getName: function() { return name; }, setAge: function(i){ if( 0<= i ){ age = i; } }, getAge: function(){ return age; } } }

  • jQuery 変数の使い方について

    jQuery 変数の使い方について 【やりたいこと】 ラジオボタンが複数ある為現在のアクションをまとめたい。 ■ $("input:radio[name='radio01']:checked").val(); の'radio01'の部分に変数を使いたい。 ■document.forms["MON"].hradio02.value の"MON"のフォーム名と、「hradio02」name部分に変数を使いたい。 http://kaicoo.blogspot.jp/2012/03/query_30.html 等を参考に元のソースから JSをまとめてみましたが、うまくいきません。 jQuery内の変数の記述方法を 教えていただけませんでしょうか? よろしくお願いいたします。 ★JSをまとめたサンプルソース <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <META http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <META http-equiv="Content-Style-Type" content="text/css"> <script src="jquery.js"></script> <script type="text/javascript" language="JavaScript"> <!-- function setVal(obj) { var formname = obj.form.name; var radioname = obj.getAttribute('name'); alert(formname); alert(radioname); //選択したラジオのvalueをhiddenに格納する document.forms[formname].h '+ radioname +' .value = $("input:radio[name='+ radioname +']:checked").val(); alert(document.forms[formname].h '+ radioname +'.value); } //--> </script> </head> <body> <table border="1"> <FORM name="MON"> <tr> <td> 結果: </td> <td> <input type="radio" name="radio01" value="良好" onClick="setVal(this);" >良好 <input type="radio" name="radio01" value="不良" onClick="setVal(this);"> 不良 <input type="hidden" name="hradio01" value="未入力です。"> </td> </tr> <tr> <td> 結果2: </td> <td> <input type="radio" name="radio02" value="良好" onClick="setVal(this);" >良好 <input type="radio" name="radio02" value="不良" onClick="setVal(this);"> 不良 <input type="hidden" name="hradio02" value="未入力です。"> </td> </tr> </table> </Form> </body> </html> ★元のソースのサンプル <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <META http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <META http-equiv="Content-Style-Type" content="text/css"> <script src="jquery.js"></script> <script type="text/javascript" language="JavaScript"> <!-- function setVal_01(obj) { document.forms["MON"].hradio01.value = $("input:radio[name='radio01']:checked").val(); alert(document.forms["MON"].hradio01.value); } //--> </script> <script type="text/javascript" language="JavaScript"> <!-- function setVal_02(obj) { document.forms["MON"].hradio02.value = $("input:radio[name='radio02']:checked").val(); alert(document.forms["MON"].hradio02.value); } //--> </script> </head> <body> <table border="1"> <FORM name="MON"> <tr><td> 結果: </td> <td><input type="radio" name="radio01" value="良好" onClick="setVal_01(this);" >良好 <input type="radio" name="radio01" value="不良" onClick="setVal_01(this);"> 不良 <input type="hidden" name="hradio01" value="未入力です。"> </td> </tr> <tr> <td> 結果2: </td> <td> <input type="radio" name="radio02" value="良好" onClick="setVal_02(this);" >良好 <input type="radio" name="radio02" value="不良" onClick="setVal_02(this);"> 不良 <input type="hidden" name="hradio02" value="未入力です。"> </td> </tr> </table> </Form> </body> </html>

専門家に質問してみよう