- ベストアンサー
コンストラクタ クロージャ
javascriptを学んでいますが、 コンストラクタとクロージャの使い道が分かりません。 どのような場合に、使うとメリットを感じるのでしょうか? よろしくお願いします。 jQueryと同時で発揮とかあるのでしょうか。。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
コンストラクタは継承(JavaScriptの継承はJavaやC系言語の継承とはその方法が違うのですが)できます。 クロージャは継承できません。 オブジェクトを生成するという意味では同じですが、コンストラクタは new を明示するから「『新しい』オブジェクトを生成する」ということが明確になります。
その他の回答 (2)
- Gotthold
- ベストアンサー率47% (396/832)
コンストラクタを使えばクラスベースのオブジェクト指向っぽいことができます。 ---- 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を外部から変更できないと言うことです。 なので、このような特性が便利なときに使えば良いかと思います。
- 神崎 渉瑠(@taloo)
- ベストアンサー率44% (1016/2280)
クロージャを使う事がどうメリットになるかどうかはわかりませんが、 まあ、読みやすさや何やらで使い分けはしています。 例題ですので実用上は不適切な書き方(メモリ消費量が多い、または実行速度が遅い)が含まれます。 実行速度は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('');