- ベストアンサー
コンストラクタ?
FireFox2のエラーコンソールで以下のようなユーザ定義クラスを作成しています。 期待する動作は、documentに、 12 と出力されることです。 が、FireFoxのエラーコンソールには、 エラー: NewClass is not a constructor ソースファイル: file:///C:82%AF%E3%83%88%E3%83%83%E3%83%97/docs/temp.html 行: 20 と表示されています。おそらく、NewClass の コンストラクタの書き方が誤っているのではないかと思いますが、webで調べても正しいコンストラクタの書き方 というのが見つけ切れませんでした。期待動作を満たす為にはどのようにかけばよいでしょうか? <script type="text/javascript"> function NewClass(){ /*ここが誤っている?*/ // } NewClass = { ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} } ClassTest = new NewClass(); document.write( ClassTest.ClassValue1 ); document.write( ClassTest.ClassValue2 ); </script>
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
> (1)と(2)の違いは、プロパティやメソッドを定義したかしないかだと > 思うのですが、ということは、プロパティやメソッドを定義してしまうと、 > 関数オブジェクトにはならないということでしょうか? 違いは、 (1)はNewClassに関数オブジェクトを代入している、 (2)はNewClassに(関数でない)オブジェクトを代入している、 ところです。 NewClassに関数オブジェクトを代入するには、 以下のような方法がありますが、 いずれにしてもfunctionキーワード(かFunctionコンストラクタ)を使わなければ、 関数オブジェクトを作ることはできません。 function NewClass(){alert("test");} NewClass = function(){alert("test");}; //名前無しの関数オブジェクトを作成して代入 NewClass = new Function('alert("test");'); //Functionコンストラクタを使用 (厳密には1番目と2,3番目は違うのかもしれませんが、試した限りではNewClassの挙動は同じでした。) それに対して(2)では、そもそも関数オブジェクトが作成されていません。 > NewClass = { > ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} > } では、オブジェクト初期化子{ }により生成されたオブジェクト(≠関数オブジェクト)を NewClassに代入しています。 (2)の方法でだめなのは、そもそもオブジェクト初期化子が関数オブジェクトを返さないためで、 プロパティやメソッドの定義は関係ありません。 例えば、 function NewClass(){/* ... */} NewClass.aaa="member_aaa"; のように関数オブジェクトNewClassにプロパティaaaを追加しても コンストラクタとして使うことはできると思います。 ただし、これでコンストラクタが返すオブジェクトに プロパティaaaが含まれるようになるわけではありません。 aaaはコンストラクタが返すオブジェクトのプロパティではなく、 あくまで関数オブジェクトNewClassのプロパティです。 (なので、関数オブジェクトにプロパティを追加する意味はあまり無いと思います。)
その他の回答 (6)
- 神崎 渉瑠(@taloo)
- ベストアンサー率44% (1016/2280)
コンストラクタについての解説は他の方の回答を見てください。 > NewClass = { > ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} > } この書き方は、「JSON」で調べてみてください。 使い方次第では非常に使いやすいです。 (個人的に「JSONオブジェクト」と呼んでますが、一種の連想配列ですね。) 配列にして NewClass=[1, 2, function(){alert('わん');}]; とすると、それぞれ NewClass[0]、NewClass[1]、NewClass[2] でアクセス出来ますが、 NewClass=[function(){alert('わん');},1,2]; としてしまうと、NewClass[0]の内容が変わってしまいます。 JSONでは、つねにNewClass['ClassValue1']でアクセス出来ますから、 代入(作成)するときの順番が変わっても問題になりません。 ただし、ループさせるときは、 for(var i=0;i<NewClass.length;i++){} ではなく for(var i in NewClass){} を使ってください。 (Safariでは配列に対して in は使えませんので、ループで取り出すときは調整しなければなりません。) > document.write( ClassTest.ClassValue1 ); > document.write( ClassTest.ClassValue2 ); この出力を実現させるだけなら、関数オブジェクトでもJSONでもどちらでも可能です 関数オブジェクト(コンストラクタを使う) function NewClass(){ this.ClassValue1=1; this.ClassValue2=2; } ClassTest=new NewClass(); オブジェクト初期化子(JSON)を使う ClassTest={ClassValue1:1, ClassValue2:2}; > ANo.1回答 > 「JavaScriptでユーザ定義のclassを作る練習」でした。 ということをしたいのであれば、関数オブジェクト(function~)を使って、newしてください。 > ↑この部分では、NewClassのメンバーを一気に定義しているのですが、 > この方法がまず誤っていますか?? 文法としては間違ってはいないんですが、 生成された物や目的が違うので何とも言えないです。
お礼
回答ありがとうございます。JSONという書き方(?)なのですね。 @ITのほうで、簡潔な書き方として紹介されていたので、そっちの意味を理解して使おうと考えたのがつまづきのもとでした。 ご教示頂いた方法とこれまでご回答頂いた件をあわせて、 理解の低いうちは、素直にfunctionキーワードで定義していくことにします。 こちらの回答も、また後日読み返させていただきたいと思います。
- urdapple
- ベストアンサー率30% (9/30)
ごめんなさい。 プロパティーの生成方法としては NewClass = { ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} } でもイイみたいですね<(>o<)> やべ、俺も素人丸出し~⌒⌒⌒⌒⌒/(;x~x)\<ごめん
お礼
いえ、回答ありがとうございます。 僕もこの指定方法にはものすごい違和感があります。
- urdapple
- ベストアンサー率30% (9/30)
ん~~そもそもJavaScript(以下:「JS」)で「クラス」を定義するというのが難しい気もしますが・・・ JSにおいてコンストラクタとはクラス(のような物)を定義する関数のことを言います。 なので・・・ function Point(x, y) { //ユーザ定義クラスの作成? this.x = x; //クラスメンバーの定義? this.y = y; //クラスメンバーの定義? } これはコンストラクタであり、クラスの宣言でもあります。 一見するとただの関数ですけど、Pointというクラスのコンストラクタです。 その後「Point」クラスのオブジェクトを生成する時は・・・ [オブジェクト名] = new Point([プロパティーx],[プロパティーy]); とすべき。 ちなみにエラーログでは NewClass is not a constructor って言われちゃっています。この場合のconstructorは、オブジェクトの生成元を参照するプロパティーとしてのコンストラクターでしょうから・・・ 「NewClass = {ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');}}って、NewClassオブジェクトに対していろいろやろうとしてるみたいだけど、そもそもNewClassって参照元は存在しないぜ!」 って言われちゃってんだと思います。 つまり・・・ NewClass = { ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} } このソースではコンストラクタとして不十分だということです。 というか、そもそも変数としてのClassValue1やClassValue2に対して、「:」(コロン)で値を代入するというやり方が、JSで許されているのかがわかりません。こういったスタイルシートチックな数値代入の方法って正規にJSに存在するのかしらん?
- Werner
- ベストアンサー率53% (395/735)
とりあえずnewが無いのはただのミスだと思います。 (newが無いとただの関数呼び出しになってしまうので。) > このコードの場合、クラスの定義はどこで、コンストラクタはどれになるのでしょうか? > また、オブジェクトの生成(インスタンス?)はどこで行っているのでしょうか? まず、JavaScriptはプロトタイプベースのオブジェクト指向言語で、 C++やJavaのようなクラスベースとは勝手が違うところがあります。 詳しくは"プロトタイプベース"などで検索してもらえば何となく分かると思いますが、 例えば以下のような解説ページが見つかります。 http://developer.mozilla.org/ja/docs/Core_JavaScript_1.5_Guide:Class-Based_vs._Prototype-Based_Languages (他の言語に比べると変わった言語ですが、使ってみるとなかなかおもしろいですよ。) > クラスの定義 とくにクラスの定義と呼べるような部分はありません。 (強いて言うならコンストラクタかな…) > コンストラクタ この場合、関数オブジェクトPointがコンストラクタです。 関数オブジェクトにnew演算子を付けて呼び出すことで、 関数オブジェクトはコンストラクタとして呼ばれます。 > オブジェクトの生成 new演算子があるところで生成されます。 またプロパティ(メンバ変数)は動的に追加できるので、 コンストラクタでプロパティを設定していなくても、 var p = new Point(10, 20); p.z = 30; などとできます。 > #1の補足 > ↑この部分では、NewClassのメンバーを一気に定義しているのですが、 > この方法がまず誤っていますか?? NewClassのプロパティ設定方法としては間違っていませんが、 これだとNewClass自身がClassValue1やClassValue2をプロパティに持つ オブジェクトになります。 (その前のfunction NewClassは上書きされているとおもいます。) コンストラクタは関数オブジェクトでなくてはならないので、 関数オブジェクトではないNewClassはコンストラクタになれません。 JavaScriptでオブジェクトを使うなら、 以下の記事も参考になると思います。 http://codezine.jp/a/authorlist.aspx?auid=167 「著者情報」内の「関係記事」
補足
詳細なフォローありがとうございます。 なるほど。すこしわかった気がします。オブジェクトと関数オブジェクトは異なるもので、宣言(?)時にプロパティを定義してしまうと、オブジェクトになってしまうので、コンストラクタとしては使えない、ということですね。 (1)function NewClass(){ /*ここが誤っている?*/ // } (2)NewClass = { ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} } (1)で定義したオブジェクト(?)が(2)で上書きされた結果オブジェクトになっているので、コンストラクタとしては使えない、のでFireFox2がエラーを出した。ここまでの理解はあっているでしょうか?? (1)と(2)の違いは、プロパティやメソッドを定義したかしないかだと 思うのですが、ということは、プロパティやメソッドを定義してしまうと、関数オブジェクトにはならないということでしょうか?
- Werner
- ベストアンサー率53% (395/735)
すでに回答がありますが、せっかく書いたのでとりあえず。 ------------------------------------------------------ <script type="text/javascript"> //コンストラクタ function NewClass(){ //プロパティ this.ClassValue1 = "value1<br>"; //プロパティ、this.ClassValue2と書くのと同じ this["ClassValue2"] = "value2<br>"; alert('わん'); } //メソッド NewClass.prototype.method1 = function(a){ return "method1:"+a+"<br>"; } var ClassTest = new NewClass(); document.write( ClassTest.ClassValue1 ); document.write( ClassTest.ClassValue2 ); document.write( ClassTest.method1("test") ); </script> ------------------------------------------------------ > webで調べても正しいコンストラクタの書き方 というのが見つけ切れませんでした。 このページはどうですか? http://www.tokumaru.org/JavaScript/
補足
参考コード、およびwebサイトありがとうございます。 参考サイトでは、 function Point(x, y) { this.x = x; this.y = y; } var p = Point(10, 20); document.writeln("p(", p.x, ", ", p.y, ")"); というコードが紹介されていますが、 ??の部分が理解できません。 このコードの場合、クラスの定義はどこで、コンストラクタはどれになるのでしょうか?また、オブジェクトの生成(インスタンス?)はどこで行っているのでしょうか? function Point(x, y) { //ユーザ定義クラスの作成? this.x = x; //クラスメンバーの定義? this.y = y; //クラスメンバーの定義? } var p = Point(10, 20); //??newを使わずにオブジェクトを生成? document.writeln("p(", p.x, ", ", p.y, ")");
- urdapple
- ベストアンサー率30% (9/30)
何がしたいのか微妙にわからないんですが、とりあえず・・・ <script type="text/javascript"> /* メソッド的にfunctionを作成する。後でクラス(?)作成時に内封する。 */ function NewClass_ClassFunc() { alert("わん"); } function NewClass() { this.ClassValue1 = 1; /* この2つは定数みたいに扱えればいいのかな? */ this.ClassValue2 = 2; /* ならこれで一応動くよ */ this.ClassFunc = NewClass_ClassFunc; /* <-メソッド的に入れる */ } var ClassTest = new NewClass(); document.write(ClassTest.ClassValue1); document.write(ClassTest.ClassValue2); </script> これで「12」って表示されるけど、こんなんでイイのかな?(^-^;
補足
すみません、12と表示を事を実現する為には だとおかしくなりますね。 このコードでやりたかったのは、 「JavaScriptでユーザ定義のclassを作る練習」でした。 NewClass = { ClassValue1:1, ClassValue2:2, ClassFunc:function() {alert('わん');} } ↑この部分では、NewClassのメンバーを一気に定義しているのですが、 この方法がまず誤っていますか?? 誤っていない場合、なぜFireFox2は ClassTest = new NewClass(); の部分で、「NewClass」が コンストラクタではない というエラーを出したのでしょうか?
お礼
再三にわたるフォローありがとうございます。 骨子としては、functionキーワードを利用して定義したものでないと、 コンストラクタにはなりえない、ということですね。 下記のように書き直して、目的を達成できました。 表示するだけ、なら簡単だったのですが、意味を理解するところでつまづきました。このQ&Aは、後日もう一度理解を深めて読み返したいと思います。 function NewClass(){ this.ClassValue1 = 1; this.ClassValue2 = 2; this.ClassFunc = function(){alert("test");}; } ClassTest = new NewClass(); document.write( ClassTest.ClassValue1 ); document.write( ClassTest.ClassValue2 ); ClassTest.ClassFunc();