たかがsetter、されどgetter。JavaSciprtでsetterとgetterを実装する4通りの方法

JavaScriptでsetterとgetterを実装する方法を集めてみた。

クロージャを使うパターン

private変数へアクセスできる特権メソッドをクロージャで実装する方法。おそらく一番メジャーな方法なので、知っている人も多いはず。

function A() {
    var a;
    this.getA = function () {
        return "a is " + a;
    };
    this.setA = function (val) {
        a = val;
    };
}
obj = new A();
obj.setA('hoge');
obj.getA();  // => "a is hoge"

__defineGetter__, __defineSetter__を使うパターン

Mozillaが作った__defineGetter__と__defineSetter__は名前からも分かるようにsetterとgetterを定義するためのもの。FirefoxChromeで一応動作するけど、ECMA非標準なので使わない方が無難。(Mozillaでもdeprecated扱いになってる)

function B() {
    var b;
    this.__defineGetter__("b", function () {
        return "b is " + b;
    });
    this.__defineSetter__("b", function (val) {
        b = val;
    });
}
obj = new B();
obj.b = 'hoge';
obj.b; // => "b is hoge"

特権メソッドを持つ無名オブジェクトを使うパターン

知らない人は「シンタックスエラーじゃないの?」と思うかも知れない。

function C() {
    var c;
    return {
        get c() {
            return "c is " + c;
        },
        set c(val) {
            c = val;
        }
    }
}
obj = C();
obj.c = 'hoge';
obj.c; // => "c is hoge"

definePropertyを使うパターン

最後がECMAScript 5で追加されたdefinePropertyを使う方法。definePropertiesというのもある。

function D() {
    var d;
    Object.defineProperty(this, "d", {
        get: function () {
            return "d is " + d;
        },
        set: function (val) {
            d = val;
        }
    });
}
obj = new D();
obj.d = 'hoge';
obj.d; // => "d is hoge"

クロージャを使えば後から追加することもできる

(function () {
    var e, f;
    Object.defineProperties(obj, {
        e: {
            get: function () { return e; },
            set: function (val) { e = 'e is ' + val }
        },
        f: {
            get: function () { return f; },
            set: function (val) { f = 'f is ' + val }
        }
    });
})();
obj.e = 'hogehoge';
obj.e; // => "e is hogehoge"
obj.f = 'hogehogehoge';
obj.f; // => "f is hogehogehoge"

他にもこんな方法あるよ!ってのがあったら教えて下さい