【问题标题】:Create multiple properties with the same getters and setters使用相同的 getter 和 setter 创建多个属性
【发布时间】:2015-04-25 13:32:36
【问题描述】:

问题

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

简而言之,我只想创建一系列相似的属性,它们将具有相同的 getter 和 setter,但 我不想为每个属性重写每个 setter 和 getter .

实施

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

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)?

【问题讨论】:

    标签: javascript setter getter getter-setter


    【解决方案1】:

    是否可以在对象的不同属性上定义相同的 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")
    });
    

    【讨论】:

    • 嗯,谢谢你详细多样的回答,我其实很喜欢闭包的方法!
    • @Thefoureye:感谢您的编辑。如果您没有删除它,我会为您的答案投赞成票以使用bind:-/
    • 只是为了挑剔,操作将value绑定到this,这就是导致意外结果的原因。 this 的范围没有改变。使用生成器函数会破坏为 value 创建单独引用的范围。
    猜你喜欢
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 2016-05-01
    • 2022-12-09
    • 2019-01-27
    相关资源
    最近更新 更多