例を次に示します。
var Bidule = function() {
this.value = 8 ;
this.calc = {
plus : function(x) { return this.value + x ; },
minus : function(x) { return this.value - x ; },
square : function() { return this.value * this.value ; }
}
this.fn = {
random : {
set : function() { return this.value = random() ; },
add : function() { return this.value += random() ; }
}
}
} ;
var b = new Bidule() ;
console.log(b.value) ; // 8
console.log(b.calc.plus(4)) ; // Error : 'this.value' is undefined.
console.log(b.fn.random.add()) ; // Error : 'this.value' is undefined.
ポイントは、「b.fn_random_add()」よりもエレガントに見えるので、クラスター化されたメソッドを持つことです。
「this」参照を修正するのは簡単です:
var _plus = b.calc.plus ;
b.calc.plus = function() {
return _plus.apply(b, arguments) ;
} ;
console.log(b.calc.plus(4)) ; // 12
ただし、以前の「this.calc.plus」も新しいセットも Bidule のプロトタイプにはありません。
次のような、独自のプロトタイプを持つサブオブジェクトを持つことを考えました。
this.calc = new Bidule_calc ;
しかし、メインオブジェクトの「this」参照を設定することはできません。
...以外の方法はありますか?:
b.calc.plus.call(b, 4) ;
... クラスタ化されたメソッドを設定して呼び出すには?
これを書いているときに、可能な解決策を見つけました:
var context = this ;
Object.defineProperty(this.calc, 'value', {
get : function() {
return context.value ;
}
}) ;
ただし、'this.calc' がプロトタイプになく、'Object.defineProperty' が Bidule の各インスタンスに対して呼び出されるため、無駄に複製された関数の問題が依然として存在するため、クラスター化されたメソッドをオーバーライドするために複製された関数が作成されます。
編集:すべてのメソッドにプロトタイプを使用する必要があることを正確にする必要があります:
var Bidule = function() {
this.value = 8 ;
} ;
Bidule.prototype = {
getValue : function() { return this.value ; }
} ;
ただし、Bidule のコンストラクターとプロトタイプには 2 つの別々のスコープがあります。これは、「var」をコンストラクターに共有してメソッドに共有できないことを意味します。