マイナー・マイナー

隠れた名作の発掘が生きがい。

JavaScriptでカプセル化のコードを書く


スポンサードリンク

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


これでカプセル化っぽいのができた!