JavaScriptのvarは変数を宣言するキーワードで、関数内でvarを指定した変数はローカル変数となります。varで指定された変数に対してのアクセス権をあれこれ探ってみます。JavaScriptで静的に追加されたメソッドからのアクセス権についての続きになります。
インスタンスを生成せずに呼び出したときの挙動
下記のようなコードを考えます。
var Data = function(info) {
var _info = info;
};
Data.setInfo = function(info) {
_info = info;
};
Data.getInfo = function() {
return _info;
};
Data関数を呼び出した後、getInfoで_infoを取得しようとする。
Data('Hoge'); document.writeln(Data.getInfo());
すると、getInfo実行時に「_info is not defined」でエラーとなる。Data関数内の_infoはvarで指定されており、その関数を抜けた後に保存されていないため。また、setInfoで値をセットしたあとにgetInfoをすると値が取れているように見えるが、これはグローバル変数に_infoをセットし、その_infoを取得しているため。
Data('Hoge'); Data.setInfo('Piyo'); document.writeln(Data.getInfo()); // Piyo document.writeln(Data.info); // undefined
インスタンス化後の挙動
Dataをインスタンス化してsetInfoやgetInfoを実行しようとすると、「has no method」となる。setInfoやgetInfoはあくまでDataに動的に追加されたメソッドであり、Dataから生成されるインスタンスには追加されない。
var hoge = new Data('Hoge'); document.writeln(hoge.getInfo()); // has no method hoge.setInfo('Hogera'); // has no method
では、インスタンス化後のオブジェクトにプライベートプロパティにアクセスするメソッドを追加したらどうか。
var Data = function(info) { var _info = info; }; var hoge = new Data('Hoge'); hoge.setInfo = function(info) { _info = info; }; hoge.getInfo = function() { return _info; }; // document.writeln(hoge.getInfo()); // _info is not defined hoge.setInfo('Piyo'); document.writeln(hoge.getInfo()); // Piyo document.writeln(hoge.info); // undefined
getInfoでは「_info is not defined」と怒られ、setInfo後のgetInfoもPiyoが取れているように見えるが、やはりグローバル変数に保存していた。var指定の変数には後から追加されたメソッドからはアクセスできない模様。
インスタンス化したDataの_infoにアクセスするためにはsetInfoやgetInfoをDataコンストラクタの中に記載しておく必要がある。これはJavaScriptでカプセル化のコードを書く - マイナー・マイナーで書いたとおりです。