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.
In a nutshell, I just 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:
The getter and setter method gives you centralized control of how a certain field is initialized and provided to the client, which makes it much easier to verify and debug. To see which thread is accessing and what values are going out, you can easily place breakpoints or a print statement.
Getters and Setters in python are often used when: We use getters & setters to add validation logic around getting and setting a value. To avoid direct access of a class field i.e. private variables cannot be accessed directly or modified by external user.
A couple things to remember: You can only have one getter or setter per name, on an object. (So you can have both one value getter and one value setter, but not two 'value' getters.)
To fix this, you need to pass a reference to the GetterAndSetter instance from class A to B . You can do this e.g. by passing it as a parameter to a method of B , or by creating a new instance of A in B and calling a method that provides an instance of GetterAndSetter .
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")
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With