使用相同的getter和setter创建多个属性

时间:2015-02-24 02:16:39

标签: javascript setter getter getter-setter

问题

最近,我一直在编写一些涉及getterssetters使用的JavaScript程序。我阅读了这两种方法的MDN文档,但是我对使用它们感到困惑。

简而言之,我只想创建一系列类似的属性,它们具有相同的getter和setter ,但是我不想重写每一个setter每个属性都有吸气剂

实施

如上所述,我尝试执行以下代码:

var defaultProperty = {
    set: function(val) {
        this.value = val - 1; // Just an example
    },

    get: function() {
        return this.value + 1; // Just an example
    }
};

var myObj = {};
Object.defineProperties(myObj, {
    foo: defaultProperty,
    bar: defaultProperty
});

然后我为foobar属性分配了新值,如下所示:

myObj.foo = 3;
myObj.bar = 7;

最后,我期待这样的事情

console.log(myObj.foo, myObj.bar);
> 3 7

但是我意外地得到了这个

> 7 7

看起来这两个属性要么指向相同的内存地址,要么共享相同的setter / getter。注意到这一点,我试图解决问题,并分别创建了每个属性,如下所示:

Object.defineProperties(myObj, {
    foo: {
        set: function(val) {
            this.value = val - 1;
        },

        get: function() {
            return this.value + 1;
        }
    },

    bar: {
        set: function(val) {
            this.value = val - 1;
        },

        get: function() {
            return this.value + 1;
        }
    }
});

但结果是一样的:

myObj.foo = 3;
myObj.bar = 7;
console.log(myObj.foo, myObj.bar);
> 7 7

我也尝试使用__defineSetter____defineGetter__函数,但结果并没有改变。

我的问题

现在,在几次尝试解决我的问题失败之后,我想知道:

  • 是否可以在对象的不同属性上定义相同的setter和getter?
  • 如果是这样,我做错了什么,为什么我的财产表现得像他们属于同一财产?
  • 有没有更好的方法来完成我想要做的事情(可能没有为每个属性编写每个setter和getter)?

1 个答案:

答案 0 :(得分:11)

  

是否可以在对象的不同属性上定义相同的setter和getter?

是的,虽然不建议你从你的经验中看出来。

  

我做错了什么,为什么我的属性表现得像是同一个属性?

因为他们存储/访问已设置/获取的值始终存储在对象的同一.value属性中:myObj.value == 6所以myObj.foomyObj.bar都会产生7

  

有没有更好的方法来完成我想要做的事情?

将值存储在闭包范围变量中,并使用函数定义属性:

function makeDefaultProperty(obj, name) {
    var value;
    return Object.defineProperty(obj, name, {
        set: function(val) {
            value = val - 1; // Just an example
        },
        get: function() {
            return value + 1; // Just an example
        }
    });
};

var myObj = {};
makeDefaultProperty(myObj, "foo");
makeDefaultProperty(myObj, "bar");

当然,您可以使用不同的“内部”属性来代替局部变量,也可以使用不同的方法通过函数创建公共setter / getter。两者都适用:

function defaultProperty(name) {
    return {
        set: function(val) {
            this[name] = val - 1; // Just an example
        },
        get: function() {
            return this[name] + 1; // Just an example
        }
    };
}

var myObj = Object.defineProperties({}, {
    foo: defaultProperty("_foo"),
    bar: defaultProperty("_bar")
});