0

昨天,我发了一篇关于原型继承和构造函数的文章。我最终确定了一种方法,该方法可以使代码保持整洁,并以可能对性能产生轻微影响为代价将原型单独放置:

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 方法与构造函数一起调用,那就太好了。这样,我可以消除整个自调用私有实例方法。

4

2 回答 2

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);
于 2012-07-26T19:55:21.297 回答
1

首先,您应该始终设置valuewith 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)
​
于 2012-07-26T19:55:06.590 回答