简体   繁体   English

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

[英]JavaScript object with public getter and setter methods

Yesterday, I posted about prototypal inheritance and constructors . 昨天,我发布了有关原型继承和构造函数的文章 I finally settled on an approach that keeps the code nice and tidy and leaves the prototype alone at the cost of possibly minor performance impact: 我最终选择了一种方法,该方法可使代码保持整洁,并以可能对性能造成较小影响为代价而将原型留给他人:

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);
}

My problem with this approach, however, is that I have to call the setValue method whenever I want to set the value of a Card instance to get the validation. 但是,这种方法的问题在于,每当我想要设置Card实例的值来进行验证时,都必须调用setValue方法。 What I'd like to do instead is have a custom setter method. 我想做的是有一个自定义的setter方法。 Here's what I have so far: 这是我到目前为止的内容:

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;
    });
}

This works well. 这很好。 Calling var card = new Card() gives me an instance with a random value, and calling card.value = null fails because it's out of range. 调用var card = new Card()会给我一个具有随机值的实例,而调用card.value = null失败,因为它超出了范围。

My problem with this, other than the fact that it is obviously much longer, is it seems like I'm duplicating some of the code. 除了明显更长的事实,我的问题还在于,似乎我正在复制某些代码。 It would be nice if the setter method was called along with the constructor. 如果将setter方法与构造函数一起调用会很好。 That way, I could eliminate the whole self-invoking private instance method. 这样,我可以消除整个自调用私有实例方法。

Functions are first class objects in Javascript, so you can totally just do something like this to eliminate the duplication: 函数是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);

First, you should always set the value with obj.value = newValue , even internally, because it invokes your validation. 首先,您应该始终使用obj.value = newValue设置value ,即使在内部也要设置,因为它会调用您的验证。 When in the constructor that means: 在构造函数中时,这意味着:

this.value = val;

But that won't work if you do it before the setter and getter are declared. 但是,如果声明setter和getter 之前执行此操作,将无法正常工作。 So move it after so that the setter function will exist when it's set. 因此,将其移到后面,以便设置器在设置时存在。


Working example here: http://jsfiddle.net/8tCjm/4/ 这里的工作示例: 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)
​

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM