2

I have a Javascript constructor with an object containing all of its fields, and functions that read/write to them:

function myObj(){
    var _settingsStore {
        setting1: 1, //default value
        setting2: 2, //default value
    }

    //gets/sets _settingsStore.settingName, does other stuff
    function _genericSet(settingName, settingValue){}
    function _genericGet(settingName){}

I'd like to programmatically create properties around each of the fields:

    for (var _setting in _settingsStore){
        var _str = _setting.toString();
        Object.defineProperties(this, {
            _str: {
                get: function() {return _genericGet(_str)},
                set: function(value) {return _genericSet(_str, value)}
            }
        })
    }

My intent is for _str to be purely a variable, and that myObj.setting1 and myObj.setting2 should be defined. Instead, the loop attempts to define myObj._str twice:

Uncaught TypeError: Cannot redefine property: _str

What's going on? And is there a way to get my desired behavior?

EDIT: To clarify, this is what I effectively want to happen, just unrolled outside of the loop:

Object.defineProperties(this, {
    settings1: {
            get: function() {return _genericGet("settings1")},
            set: function(value) {return _genericSet("settings1", value)}
        },
    settings2: {
            get: function() {return _genericGet("settings2")},
            set: function(value) {return _genericSet("settings2", value)}
        },
        //and so on, if there are more of them
    })
4

2 回答 2

3

我要重新开始了。如果你只想使用 setter 和 getter 做一些额外的工作,并且每个对象都隐藏在构造函数中,并且你想重用一些通用函数,你可以这样做:

function myObj(){
    var _settingsStore = {
        setting1: 1, //default value
        setting2: 2, //default value
    }

    for (var _setting in _settingsStore){
        makeGetSet(this, _setting, _settingStore);
    }
}

function makeGetSet(obj, key, store) {
    Object.defineProperty(obj, key, {
        get: function() { return _genericGet(key, store)}
        set: function(val) {_genericSet(key, val, store)}
    })
}

function _genericGet(key, store){
    var val = store[key];
    // manipulate the val
    return val
}
function _genericSet(key, val, store){
    // manipulate the new val
    store[key] = val
}

我真的不知道您在获取/设置时正在做什么类型的操作,因此其中一些可能会缩短。

此外,您可以制作_settingsStore泛型,并且只使用变量范围来存储值,因为无论如何您都需要它。

于 2013-05-08T17:26:06.767 回答
1

您误解了对象文字。

{ _str: blah }是一个具有名为 的属性的对象_str;它不使用_str变量的值。

因此,您实际上每次都定义相同的名称。
由于您没有设置configurable: true,因此引发了错误。

相反,您应该调用Object.defineProperty(singular),它接受一个字符串后跟一个属性名称。
(或者,您可以构建一个要传递defineProperties给它的对象,并使用索引器表示法给它正确的名称)

但是,您的代码仍然无法正常工作,因为所有回调都将关闭同一个变量(Javascript 没有块范围)。
为了解决这个问题,您需要将每个迭代包装在一个单独的函数中。

于 2013-05-08T16:40:42.510 回答