現代的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だけとか全然アリです。
参考
- ECMAScript 2015 Language Specification – ECMA-262 6th Edition
- 7.3.7 DefinePropertyOrThrow (O, P, desc) …
Object.defineProperty()の仕様、だと思う - 9.1.6 [[DefineOwnProperty]] (P, Desc) …
Object.defineProperty()の第三引数の扱いについて、だと思う - 14.3 Method Definitions … get/setの書式
- 7.3.7 DefinePropertyOrThrow (O, P, desc) …
- getter – JavaScript | MDN
- setter – JavaScript リダイレクト 1 | MDN … あれ、なんかタイトルとURLが変?
- Object.defineProperty() – JavaScript | MDN … 日本語版は『不完全』らしい