thisとvarでの変数宣言の違いなど教えていただけないでしょうか?

このQ&Aのポイント
  • コンストラクタ(プロトタイプ)では、関数内にthisで変数宣言し、クロージャではvarで変数宣言する。
  • コンストラクタ(プロトタイプ)において、thisで宣言された変数はインスタンス化されたオブジェクトのメンバー変数としてアクセス可能であり、varで宣言された変数はプライベート変数として機能する。
  • クロージャでは、varで宣言された変数はクロージャ内部でのみアクセス可能であり、外部からのアクセスは制限される。また、varで宣言された変数はプライベート変数として機能する。
回答を見る
  • ベストアンサー

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; } } }

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

  • ベストアンサー
  • Ogre7077
  • ベストアンサー率65% (170/258)
回答No.1

JavaScript において "this.名前" は「コンテキストオブジェクト」にプロパティを生成する構文です "var 名前" は「関数スコープ」に変数を生成する構文です プロパティは、対象のオブジェクトさえ分かれば、何れのスコープからでも参照できます 関数スコープの変数は、同一スコープまたは変数を束縛したクロージャーからのみ見えます この違いを利用して、オブジェクト指向のカプセル化を表現するために、 * public メンバなら this.名前 * private メンバなら var 名前 * private へのgetter/setterなら クロージャー を使うことが多いです。 例: function Person(n,a) { this.name = n; // public var age = a; // private this.getAge = function(){return (age>17)? 17: age}; // getter } var o = new Person('花子',29); alert(o.name); // 花子 alert(o.age); // undefined alert(o.getAge()); // 17

hp_win7
質問者

お礼

ご回答ありがとうございます。 とても分かりやすく助かりました。

その他の回答 (1)

  • notnot
  • ベストアンサー率47% (4843/10252)
回答No.2

「thisで変数宣言」? this.name = n; をnameという変数の宣言だと思っているのでしょうか?それは間違いです。 これは、プロパティーの設定です。 もし、これが変数宣言であると書いてあるような入門書を読んでいるなら、その本は捨てた方が良いと思いますよ。 プロパティについて調べると違いがわかるかと思います。

hp_win7
質問者

お礼

ご回答ありがとうございます。 大きな勘違いをしていたようです。 助かりました

関連する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 を付けなくても生成できる

  • コンストラクタでvar ?

    javascriptのコンストラクタについて。 下記のコードで、変数を2つ宣言しています(★)が、 下部のfor文で、その変数名を引数のstr,numにすれば、★での宣言は不要ですか? 宣言しとくと何かメリットがあるのでしょうか? var Repeater = function(str, num){ var string = str, //★ number = num;     //★ this.repeat = function (){ var i, result = ""; for(i = 0; i < number; i++ ) { result += string; } return result; }; }; new Repeater("abc", 3).repeat(); あるサイトから引用

  • thisで定義したプロパティが継承できない

    以下のようなコードがあります。 function inherit(subClass, superClass) { for (var prop in superClass.prototype) { if (typeof(subClass.prototype[prop]) == "undefined") { subClass.prototype[prop] = superClass.prototype[prop]; } } } /* class Personal */ { function personal() { this.sex = "男"; } personal.prototype = { "hello" : "こんにちは", "fName" : "苗字", "lName" : "名前", "age" : "年齢" } } /* class Taku17 */ { function taku17() { this.lName = "taku17"; } taku.prototype = { "fName" : "Secret", "age" : 21, "tall" : "1234cm", "height" : "5678Kg", "getFullName" : function() { return this.fName+" "+this.lName; } }; inherit(taku17, personal); } var source = ""; window.onload = function() { var person1 = new taku17(); source += "person1.hello = "+person1.hello+"<br />"; source += "person1.fName = "+person1.fName+"<br />"; source += "person1.lName = "+person1.lName+"<br />"; source += "person1.age = "+person1.age+"<br />"; source += "person1.sex = "+person1.sex+"<br />"; source += "person1.tall = "+person1.tall+"<br />"; source += "person1.height = "+person1.height+"<br />"; source += "person1.getFullName() = "+person1.getFullName()+"<br /><br />"; document.getElementById("result").innerHTML = source.replace(/undefined/g, "<font color=\"#ff0000\">undefined</font>"); } Javascriptでクラス化と継承を実現するためのコードなのですが、出力される情報のうちsexの情報だけがundefinedになってしまいます。sexプロパティはpersonal関数(コンストラクタのつもり)内にthis.sexとして定義してあり、他のプロパティはprototypeで定義してあります。このsexプロパティも継承するにはどのようにしたら良いのでしょうか?色々試してみましたが、そもそもsexプロパティにアクセスする方法から分かりません。

  • php クラス

    phpエクラスの勉強をしているのですが、参考書に書いているメンバ変数に値を代入している意味がよくわからないので教えてください。メンバ変数の値を書かなくtも動作できるのになぜ必要なのでしょうか? 参考書 <html> <head> <title>サンプル</title> </head> <body> <?php $pr = new Person; $pr->name = "鈴木"; $pr->age = 56; ?> <table border="2"> <tr bgcolor="#AAAAAA"> <th>名前</th> <th>年齢</th> </tr> <?php print "<tr><td>"; print $pr->getname(); print "</td><td>"; print $pr->getage(); print "</td></tr>"; ?> </table> <?php class Person { public $name ="姓名"; public $age = 20; function getname(){return $this->name;} function getage(){return $this->age;} } ?> </body> </html> テスト <?php class Person { public $name ;←ここに値を格納する意味 public $age ;←ここに値を格納する意味 function getname(){return $this->name;} function getage(){return $this->age;} } ?>

    • ベストアンサー
    • PHP
  • 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の書き方

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

  • jQueryのvar jQueryの仕組みについて

    jQuery-1.6.2のソースコードを見ているのですが質問させてください。 25行目の var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); }, そして100行めの jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { の意味が分かりません。 PHP等のclassになれているとJSのクラスは戸惑うことが多いのですが、この例は最たるもので、自分の中のJSでのclassは (1)スーパークラスのプロパティをcall()、apply()で継承 (2)スーパークラスのメソッドをprototypeオブジェクトで継承 (3)インスタンスのデータ型判定に必要なプロパティをconstructorで調整 だったのですが、スーパークラスがどの行のどれなのかも分かりません。 型やメソッド名からこれらがclassを意味しているのは分かるのですが、いったいどの部分がclass定義、継承を行っているのか教えていただけませんでしょうか? なぜこれらがclassになっているのかが理解できません。 分るのは、jQuery.prototype.constructor = jQueryで、それをjQuery.fnに代入((3))している事です。 329行目の、jQuery.fn.init.prototype = jQuery.fn;の右辺がnew {$class}の形であれば(2)のプロトタイプチェーンの形だと分るのですが。 (1)は、init内でメンバ変数を定義したりしているので、classなのかな、という程度しか分っておりません。 jQuery.fnがコンストラクタで、jQueryがインスタンスで、var jQueryは親クラスをinitしたもの?・・・と混乱しております。 質問内容も文章が混乱していて申し訳ないです。

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

    立て続けに質問することをお許し下さい。。 以下のような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 : "白色人種" }; /********************************************/ 多分、初めに行ったコンストラクタの定義とこの{}の定義とが競合しているためだと思うのですが、何かよい書き方ありませんでしょうか。

  • トリッキーなJSの文法(prototype.jsなど)が分かりません

    Ajaxの「prototype」( http://www.prototypejs.org/ )などで 下記のようなfunctionの記述方法をよく見かけます。 ▼Prototype.js(ver1.5.0) 20行目抜粋 ---------------------------------------- var Class = {  create: function() {   return function() {    this.initialize.apply(this, arguments);   }  } } -------------------------------------------- でも、私には高度すぎて以下の点がどうしても読み解けません。  (1)var Class = {~~~~~~} が、何をしているのか分かりません。    配列なら[ ]ですし関数か何かを省略した宣言の記述方法なのでしょうか?  (2)create: が何なのか分かりません。必死で調べたら型を宣言しているような感じでしたが、    見慣れない「:」を使ったプログラムで検討もつきません。 私が知っているfunction宣言はこの2パターンのみしか知りません。 ・一般的なfunction宣言  function test(hikisu){   //処理内容  } ・無名関数でのfunction宣言  var a = function(x) {   //処理内容  } ぜひ教えていただけませんでしょうか。 どうぞよろしくお願いします。

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

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