JavaScriptでカプセル化みたいなのってできるんかなー、と思ってカプセル化のやり方を色々調べました。プロパティを1つ持ち、そのプロパティに対するgetterとsetterを持つオブジェクトの実装を考えます。
thisキーワードは自身のインスタンスを指すキーワードです。変数にthisキーワードを指定することでプロパティを設定できます。けれど、このままでは"クラス名.プロパティ名"で直接アクセスできてしまいます。
function Name(name) { this.name = name; this.setName = function(name) { this.name = name; } this.getName = function() { return this.name; } } var MyName = new Name('Hoge'); document.writeln(MyName.getName()); // Hoge MyName.setName('Piyo'); document.writeln(MyName.getName()); // Piyo document.writeln(MyName.name); // Piyo
varで変数を宣言すれば、その変数は関数の外からはアクセスできなくなります。なので、下記のようなコードはうまくいきそうだけれど、今度はアクセサがうまく機能しなかったです。
function Name(name) { var name = name; this.setName = function(name) { name = name; // (A) } this.getName = function() { return name; } } var MyName = new Name('Hoge'); document.writeln(MyName.getName()); // Hoge MyName.setName('Piyo'); document.writeln(MyName.getName()); // Hoge document.writeln(MyName.name); // undefined
(A)の部分が明らかにおかしい。thisをつけても解決しない。JavaScriptでは変数と引数に同名の名前を付けない方針が良さそうです。調べてみると、プライベートなプロパティには変数名の前にアンダースコアを付けるのが慣例っぽいです。
function Name(name) { var _name = name; this.setName = function(name) { _name = name; } this.getName = function() { return _name; } } var MyName = new Name('Hoge'); document.writeln(MyName.getName()); // (1) Hoge MyName.setName('Piyo'); document.writeln(MyName.getName()); // (2) Piyo document.writeln(MyName._name); // (3) undefined
これでカプセル化っぽいのができた!