javascriptでprivate変数へのアクセサをクラスに定義する関数
関数本体
Object.attr_accessor = function(obj, name, initval) { obj[name] = (function() { var value; return function() { return arguments.length ? value = arguments[0] : value; }; })(); if (initval) obj[name](initval); return obj; }; Object.attr_reader = function(obj, name, initval) { Object.attr_accessor(obj, name, initval); var _attr = obj[name]; obj[name] = function(){ return _attr.call() }; }
オブジェクトにprivateなプロパティとsetter, getterを定義する。
プロパティに引数有りでアクセスした場合setterになり、
引数無しの場合getterとなる。setterの場合も戻り値はgetterと同じ。
使い方
// クラスに追加 var MyClass = function(){}; MyClass.prototype = { attr: function() { return Object.attr_accessor.apply(null, [this].concat(Array.prototype.slice.call(arguments, 0)) ); }, attr_r: function() { return Object.attr_reader.apply(null, [this].concat(Array.prototype.slice.call(arguments, 0)) ); } } // オブジェクト毎にアクセサを追加 var obj = new MyClass(); obj.attr("test"); obj.test("hogehoge"); alert(obj.test()); //-> 「hogehoge」 // 追加と同時に初期化も行う obj.attr("test2", 100); alert(obj.test2()); //-> 「100」
クラスに追加せずにObject.attr_accessor(obj, "propname")としてやっても良い。
コンストラクタでアクセサ定義
var MyClass2 = function(){ this.attr("test"); this.attr("test2", 500); } MyClass2.prototype.attr = function() { return Object.attr_accessor.apply(null, [this].concat(Array.prototype.slice.call(arguments, 0)) ); }; var obj2 = new MyClass2(); obj2.test("hogehoge"); alert(obj2.test()); //-> 「hogehoge」 alert(obj2.test2()); //-> 「500」
readonlyにする
var MyClass3 = function(){ this.attr_r("test", "foobar"); } MyClass3.prototype.attr = function(name, init) { return Object.attr_reader.apply(null, [this, name, init]); } var obj3 = new MyClass3(); alert(obj.test()); //-> 「foobar」 alert(obj.test("overwrite")); //-> 「foobar」
readonlyで定義すると内部からの書き換えもできないし、
そうでないと外からも書き換え自由だし、使いどころがわからない。。。
java好きの為のsetter, getterといったところか。
クラス内からだけ書き換えられて外からはreadonlyにできたら理想だけど。