具有公共getter和setter方法的JavaScript对象

时间:2012-07-26 19:48:01

标签: javascript class inheritance constructor prototype

昨天,我发布了prototypal inheritance and constructors。我最终确定了一种方法,可以使代码保持整洁,并以可能对性能产生轻微影响为代价而保留原型:

function Card(value) {
    // setValue is a public instance method
    this.setValue = function (val) {
        if (!range[val]) {
            val = drawRandom();
        }

        // value is a public instance variable
        this.value = val;

        return val;
    };

    this.setValue(value);
}

然而,这种方法的问题在于,每当我想设置Card实例的值以获得验证时,我都必须调用setValue方法。我想做的是使用自定义setter方法。这是我到目前为止所做的:

function Card(val) {
    // value is a private instance variable
    var value;

    // This is a private instance method
    // It's also self-invoking, but that's beside the point
    (function (x) {
        if (!range[x]) {
            x = drawRandom();
        }

        value = x;
    }(val));

    this.__defineGetter__("value", function () {
        return value;
    });

    // Some code duplication
    this.__defineSetter__("value", function (x) {
        if (!range[x]) {
            return false;
        }

        value = x;

        return x;
    });
}

这很有效。调用var card = new Card()会为我提供一个具有随机值的实例,并且调用card.value = null会失败,因为它超出了范围。

我的问题,除了它显然更长的事实,似乎我复制了一些代码。如果setter方法与构造函数一起调用会很好。这样,我可以消除整个自我调用的私有实例方法。

2 个答案:

答案 0 :(得分:2)

函数是Javascript中的第一类对象,所以你可以完全做这样的事情来消除重复:

function setter (x) {
    if (!range[x]) {
        return false;
    }
    return x;
}
(function (x) {
    value = setter(x);
    if (!value) {
        value = drawRandom();
    }

}(val));

this.__defineGetter__("value", function () {
    return value;
});

// Some code duplication
this.__defineSetter__("value", setter);

答案 1 :(得分:1)

首先,您应始终将value设置为obj.value = newValue,甚至在内部,因为它会调用您的验证。在构造函数中意味着:

this.value = val;

但是如果你在之前这样做就行不通知了setter和getter。所以在之后移动,以便setter函数在设置时就存在。


这里的工作示例:http://jsfiddle.net/8tCjm/4/

var drawRandom = function () {
    return Math.floor(Math.random() * 3) + 1;
};

var range = {
    1: 'Ace',
    2: 'Two',
    3: 'Three'
};

function Card(val) {
    var value;

    this.__defineGetter__('value', function () {
        return value;
    });

    this.__defineSetter__('value', function (x) {
        if (range[x]) {
            value = x;
        } else {
            value = drawRandom();
        }

        return value;
    });

    this.value = val;
};

console.log(new Card(1).value); // 1
console.log(new Card(2).value); // 2
console.log(new Card(3).value); // 3

console.log(new Card(987).value); // not 987 (1-3)
​