• ベストアンサー

コンストラクタ クロージャ

javascriptを学んでいますが、 コンストラクタとクロージャの使い道が分かりません。 どのような場合に、使うとメリットを感じるのでしょうか? よろしくお願いします。 jQueryと同時で発揮とかあるのでしょうか。。

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

  • ベストアンサー
回答No.1

コンストラクタは継承(JavaScriptの継承はJavaやC系言語の継承とはその方法が違うのですが)できます。 クロージャは継承できません。 オブジェクトを生成するという意味では同じですが、コンストラクタは new を明示するから「『新しい』オブジェクトを生成する」ということが明確になります。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • Gotthold
  • ベストアンサー率47% (396/832)
回答No.3

コンストラクタを使えばクラスベースのオブジェクト指向っぽいことができます。 ---- function Person(name, age){  this.name = name;  this.age = age; } Person.prototype.say = function(){  alert("name="+this.name+", age="+this.age); } var person1 = new Person("Suzuki",20); var person2 = new Person("Satou",30); person1.say(); person2.say(); ---- 似たようなことは ---- var person1 = {name: "Suzuki", age:20, say: function(){alert("name="+this.name+", age="+this.age);}}; ---- のようにnewを使わなくてもできますが、 newを使うと生成されたオブジェクトにプロトタイプが設定されるので、 各オブジェクトに共通なプロパティの設定や プロトタイプチェーンを使った継承などが実現できます。 なお、newをつけなくても オブジェクトが生成されるようにするには、 以下のような記述にします。 ---- function Person(name, age) {  //ここで内部的にnewする。  return new Person.fn.init(name, age); } Person.fn = {  init: function(name, age){   this.name = name;   this.age = age;  },  say: function(){   alert("name="+this.name+", age="+this.age);  } }; Person.fn.init.prototype = Person.fn; var person1 = Person("Suzuki",20); //こっちではnew不要 var person2 = new Person("Satou",30); //newを付けても動く person1.say(); person2.say(); ---- jQueryもこのような記述をしているので、 new $(...); の様にユーザーがnewを付けなくても動作するようになってます。 (というか、上記の記述はjQueryのソースコードを参考にしました。) クロージャは、典型的には関数を入れ子にして 内側の関数をreturnしたときにその効果が見えてきます。 ---- function make_counter(name){  var count = 0;  return function(){   count++;   alert(name+":"+count);  } } var c1 = make_counter("A"); var c2 = make_counter("B"); c1(); //A:1 c1(); //A:2 c1(); //A:3 c2(); //B:1 c2(); //B:2 c2(); //B:3 c1(); //A:4 c2(); //B:4 ---- ここで注目するところは、 c1とc2でnameとcountが別々に保持できていることと、 nameとcountを外部から変更できないと言うことです。 なので、このような特性が便利なときに使えば良いかと思います。

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

クロージャを使う事がどうメリットになるかどうかはわかりませんが、 まあ、読みやすさや何やらで使い分けはしています。 例題ですので実用上は不適切な書き方(メモリ消費量が多い、または実行速度が遅い)が含まれます。 実行速度は1万回呼び出して20~1000ミリ秒程度と思いますが、メモリ消費量はスマホ、タブレットでは動作に支障が出るかもです。 function myClosure(arg){ var value = arg; function getValue(){ return value; } var accessor = { getValue: getValue } return accessor; } function myConstructor(arg){ this.value = arg; //プロパティ var name = 'mycon'; // クロージャ this.getName = function(){ return name; } this.setName = function(arg){ name = arg; } } myConstructor.prototype = { getValue: function(){ return this.value; } }; var a1 = myClosure('hello') var a2 = myClosure('HELLO'); var b1 = new myConstructor('world'); var b2 = new myConstructor('WORLD'); b2.setName('const'); alert( a1.getValue() ); //'hello' alert( a2.getValue() ); //'HELLO' alert( b1.getValue() ); //'world' alert( b2.getValue() ); //'WORLD' //alert( value ); // 未定義エラー //alert( name ); // 未定義エラー alert( b1.getName() ); //'mycon' alert( b2.getName() ); //'const' ------------ なお、先にnewの明示について書いていますが、 new myClosure()としても期待通り動きます。 ですがコンストラクタでnewを付けずに呼び出すと、期待通り動きません。 var a3 = new myClosure('Hello, World'); alert( a3.getValue ); // 'Hello, World' というわけで、newを付けても付けなくても大丈夫なように、なおかつ継承ができるように、と、 クロージャとしてコンストラクタを使う方法が、ベストプラクティスとして挙げられています。 かなり複雑になりますが、だいたいこんな感じかと。 function myCinC(arg){ function myConstructor(arg){ //コンストラクタを定義 this.value = arg; } myConstructor.prototype ={ /*略*/ }; var accessor = new myConstructor(arg); // コンストラクタを元にクロージャを生成 return accessor; } var c1 = myCinC(''); var c2 = new myCinC('');

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • クロージャ

    javascriptのクロージャについて。 クロージャにnewは必要ですか? コンストラクタであれば、newでオブジェクトを生成しますが、クロージャはどうでしょうか? クロージャ-------------------- 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; } } } var p = new Person('Hanako', 3); // new を付けなくても生成できる

  • コンストラクタについて

    プログラム初心者です classを使うときに使うコンストラクタについて教えてください なぜ自動で実行できるのか不思議です 質問1 このコンストラクタの使い道を教えてください。 質問2 PHPはC言語で作られているのですよね?コンストラクタを自動で実行しているC言語の処理はどうなっているのですか? 質問3 classと関数の違いがわかりません。ネットで調べると「classだと変数を保持できる」とでますが関数だと保持できないのでしょうか? よろしくお願いします

    • ベストアンサー
    • PHP
  • クロージャーの利点が理解できない

    クロージャーの利点はグローバル変数を使わずにコードがかけると認識しているのですが、 http://dqn.sakusakutto.jp/2009/01/javascript_4.html だとcがグローバルじゃないけどfがグローバル変数なんで結局グローバル変数が存在する事になって意味がないような気がします。 他のサンプルでもだいたいこんな形です。 それでもクロージャー使う方がいいのでしょうか? ご教示頂けると幸いです。

  • コンストラクタって?

     ↓    ↓    ↓ クラスを基にインスタンス化を行いますが このときに初期化を行わなくてはならないことがあります。 それを実現するのが「コンストラクタ」です。 のような解説はたくさん読んできたのですが 具体的にどういう場合にコンストラクタを使用するのでしょうか? プログラムには必ずコンストラクタは必要なんですか? 例えばシューティングゲームを作るときの こういう処理にコンストラクタが役立つんだよー! などという具体的な例があればぜひ教えてください。 どなたかご協力よろしくお願いします!

    • ベストアンサー
    • Java
  • javascriptのクロージャが理解できずに苦しんでいます。

    javascriptのクロージャが理解できずに苦しんでいます。 下記のようなコードをよく見るのですが、a()とfuncA()()が等価のようなのですが 実行するとa()の場合のみ変数の値が維持されます。 a()とfuncA()()の違いを理解したいと思っています。 どなたかどうぞよろしくお願い致します。 またクロージャのわかりやすい解説サイトなどご存知の方いらっしゃいましたら 合わせてよろしくお願い致します。 function funcA() { var i = 10; return function() { i++; alert(i); }; }; var a = funcA(); console.log(a() === funcA()())//true funcA()();//11 funcA()();//11 funcA()();//11 a();//11 a();//12 a();//13

  • コンストラクタ

    恐れ入ります。 たとえばSample classを定義するとして class Sample{ int a=0; int b=0; Sample(){ //まあ、この場合は通常省略ですが。 } } とコンストラクタの前に処理を書く場合と、 class Sample{    Sample(){ int a=0; int b=0; } とコンストラクタに書く場合とでは何か違いがあるのでしょうか?本を見ると「コンストラクタはインスタンスが生成されたときに呼び出される処理」とありますが、上のような記述でも「生成されたときに処理」されますよね・・・? インスタンスを生成するときに引数を使う場合には違いはわかるのですが・・・? 引数がない場合には「コンストラクタには意味はない」であっていますか?

    • ベストアンサー
    • Java
  • コンストラクタについて

    VCの勉強をしています。 ちょっとショッキングなことを聞いてしまいました。 クラスのインスタンスを作成した場合、 コンストラクタは継承もとのコンストラクタもよばれる?? これって本当ですか!! MFCだとクラスの階層はだいぶ深いです。 例えば基本のCviewなんかはCObject>CCmdTarget>CWnd>Cviewの順に継承されています。 MFCでは更にCViewを継承したCTestViewなんてクラスがコードの主役です。 それでCTestViewのインスタンスを作成した場合、 コンストラクタはCTestViewのコンストラクタだけ実行すると思いますが、 ショッキングな内容ではCViewのコンストラクタも実行されてます。 これって本当にそうなるのでしょうか。 もし、そうならコンストラクタはてっぺんのCObjectから順に実行されますか。 それとも1つ上の継承先だけですか。 また、何でこんな仕組みにする必要があるのですか? 更にいえばCObjectにはSerializeという関数があります。 これをCTestView.serializeとした場合、 CObjectから順々にSerializeが呼び出されているのでしょうか? そんなことあるわけないよと、あまりにもバカバカしいのですが、 知人がそうだと言い張るのでよろしくお願いします。

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

    ネットで検索したりして調べているのですがいまいちわからなかった箇所が あるので質問させていただきます。 コンストラクタで設定するのとプロトタイプで設定する違いがいまいちわかりません。 例えば 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>

  • js コンストラクタ関数 解釈

    javascript コンストラクタ関数 jsのコンストラクタ関数と普通の関数の相違点は 「new」を付けて関数を呼ぶかどうかでコンストラクタ関数は初期化しているという解釈は間違っていますか?

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

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

OUTLOOK送受信のエラー
このQ&Aのポイント
  • OUTLOOK送受信でエラーが発生しました:メッセージの送信ができません
  • アドレスの設定を確認してもエラーが解消されない
  • NEC 121wareでのメール送受信に問題がある
回答を見る