現代的JavaScriptおれおれアドベントカレンダー2017 – 05日目

getter/setterとは、普通のプロパティのように見えて実は関数、てなやつです。 document.cookie がそれ的な感じですね。最近あんまり使わない気がするけど。

使い方

まずこんな感じで get xxx と set xxx を定義しまして。

var obj = {
  get name() {
    console.log('get()', this._name);
    return this._name;
  },

  set name(value) {
    const sValue = String(value);
    const name = sValue.charAt(0).toUpperCase() + sValue.slice(1).toLowerCase();  // capitalize
    console.log('set()', this._name, '->', name);
    this._name = name;
  },
};

使う側は普通のプロパティと同様にアクセスします。

obj.name = 'alice';
console.log('Name:', obj.name);  // "Alice"

obj.name = 'BOB';
console.log('Name:', obj.name);  // "Bob"

値保持用のプロパティ

を別途、関数の外に持っていないといけないのがちょっとアレ。

JavaScript村では「アンダースコアから始まるプロパティはprivateなものとみなす」という昔からの風習があるので、それを利用するとよろしいかと存じます。

obj._name とか書いちゃうのは駄目ということになっている、ってことです。

delete で削除も

できます。

delete obj.name;
obj.name = 'cHARLIE';
console.log(obj.name);  // "cHARLIE"

普通のプロパティと一緒ですね。

後から追加する

既に存在するオブジェクトでも、 Object.defineProperty() を使ってgetter/setterを追加できます。

var obj = {};
Object.defineProperty(obj, 'name', {
  get() {
    console.log('get()', this._name);
    return this._name;
  },

  set(value) {
    const sValue = String(value);
    const name = sValue.charAt(0).toUpperCase() + sValue.slice(1).toLowerCase();  // capitalize
    console.log('set()', this._name, '->', name);
    this._name = name;
  },
});
obj.name = 'alice';
console.log('Name:', obj.name);  // "Alice"

obj.name = 'BOB';
console.log('Name:', obj.name);  // "Bob"

他にも enumerable とか、いろいろ機能があります。個人的にはget/setだけ知ってれば良いかなーとか思ってます。

あ、ちなみに value というのもあるんだけど、get/setで扱う値を保持する用途ではないです。

メソッドの書き方

さりげなく書きましたけど、 function の記述を省略することができます。

var obj = {
  foo() {},
  function bar() {},
};

別稿参照。

クラスで使う

クラスでもget/setを書けます。

class Person {
  constructor(name) {
    this.name = name;
  }

  get name() {
    console.log('get()', this._name);
    return this._name;
  }

  set name(value) {
    const sValue = String(value);
    const name = sValue.charAt(0).toUpperCase() + sValue.slice(1).toLowerCase();  // capitalize
    console.log('set()', this._name, '->', name);
    this._name = name;
  }
}
var obj = new Person('alice');
console.log('Name:', obj.name);

obj.name = 'bob';
console.log('Name:', obj.name);

その他

ES2015 (ES6) じゃなくてES5.1(2011年)で追加されました。

でもどうしてもお伝えしたくて。ごめんね。

あと両方を作る必要はないです。setterだけとか全然アリです。

参考