Reputation: 4794
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
})
Upvotes: 2
Views: 200
Reputation:
I'm starting over. If you just want to use setters and getters that do some extra work, and each object has its on store hidden in the constructor, and you wanted to reuse some generic functions, you could do this:
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
}
I really don't know what sort of manipulations you're doing when getting/setting, so some of this could maybe be shortened.
Also, you could make the _settingsStore
generic, and just use the variable scope for the value storage since you need that anyway.
Upvotes: 3
Reputation: 887453
You're misunderstanding object literals.
{ _str: blah }
is an object with a property named _str
; it doesn't use the value of the _str
variable.
Therefore, you were actually defining the same name every time.
Since you didn't set configurable: true
, that threw an error.
Instead, you should call Object.defineProperty
(singular), which takes a string followed by a property name.
(alternatively, you could build an object to pass to defineProperties
and give it the correct name using indexer notation)
However, your code still won't work correctly, since all of the callbacks will close over the same variable (Javascript does not have block scope).
To solve that, you need to wrap each iteration in a separate function.
Upvotes: 1