Recently I've been writing some JavaScript program which involves the use of getters and setters. I read the MDN documentation for both methods, but I got confused trying to use them.
I want to create a series of similar properties, which will have the same getters and setters, but I don't want to rewrite every single setter and getter for every property.
Stated the above, I tried executing the following code:
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
});
Then I assigned new values to my foo
and bar
properties, like this:
myObj.foo = 3;
myObj.bar = 7;
And, finally, I was expecting something like this:
console.log(myObj.foo, myObj.bar);
> 3 7
But I unexpectedly got this instead:
> 7 7
It looks like the two properties are either referring to the same memory address or sharing the same setters/getters. Noticed this, I tried to solve the problem, and created each property separately, like this:
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;
}
}
});
But the result was the same:
myObj.foo = 3;
myObj.bar = 7;
console.log(myObj.foo, myObj.bar);
> 7 7
I also tried using the __defineSetter__
and __defineGetter__
functions, but the result didn't change.
Now, after several failed attempts to solve my problems, I'm wondering:
Is it possible to define the same setters and getters on different properties of an object?
Yes, although it's not recommended as you can see from your experience.
what am I doing wrong, and why do my properties behave like they're the same property?
Because they store/access the value that was set/gotten is always stored in the same .value
property on your object: myObj.value == 6
so both myObj.foo
and myObj.bar
yield 7
.
Is there any better method to accomplish what I'm trying to do?
Store the values in closure scope variables, and use a function to define the properties:
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");
Of course, instead of the local variable you simply might use distinct "internal" properties, and you might also use a different way of creating the common setters/getters by a function. Both applied:
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")
});