子集对象中的JavaScript聚类方法

时间:2013-05-31 21:24:40

标签: javascript object methods

以下是一个例子:

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'不在原型中,并且将为每个Bidule实例调用'Object.defineProperty',因此仍然存在无用的重复函数的问题,因此将创建重复的函数来覆盖聚类方法。


编辑: 我必须准确地说,我们必须为所有方法使用原型:

var Bidule = function() {
    this.value = 8 ;
} ;
Bidule.prototype = {
    getValue : function() { return this.value ; }
} ;

尽管如此,Bidule的构造函数和原型有两个独立的范围。 这意味着我们不能将“var”共享到构造函数中以与方法共享。

1 个答案:

答案 0 :(得分:3)

只需将要使用的范围保存到变量即可。在JSFiddle中测试过。

var Bidule = function() {
    var self = this;
    this.value = 8 ;

    this.calc = {
        plus : function(x) { return self.value + x ; },
        minus : function(x) { return self.value - x ; },
        square : function() { return self.value * self.value ; }
    }

    this.fn = {
        random : {
            set : function() { return self.value = random() ; },
            add : function() { return self.value += random() ; }
        }
    }
} ;