0

On MDN there is a sample example showing get and set used on an object initialization:

var o = {
  property: function ([parameters]) {},
  get property() {},
  set property(value) {}
};

Without any example showing how to use that structure I always enter in an infinite loop, for example:

var o = {
  property: function (test) {return "test"},
  get property() {return this.property;},
  set property(value) {this.property = value;}
};

When I try to access the object property named property an infinite loop starts, which I assume is because the get also triggers itself when trying to read the property it gets.

console.log(o.property); // infinite loop occurs

So I am assuming that I am doing this wrong, but in that case the example on that web page is not very clear. The temporary solution I found was to save the value in a similar property (_property for example), but I would like to not do this and keep the property name intact for the object, getter and setter.

Is this possible and if so how to do it correctly?

Shadow
  • 4,168
  • 5
  • 41
  • 72
  • That's nothing but a syntax showcase (and a rather confusing one, showing both a data and an accessor property with the same name). For actual examples you should read [the guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects) – Bergi May 08 '17 at 06:20
  • Do *what* correctly? I'm not sure what the expected behaviour of your `o.property` is. – Bergi May 08 '17 at 06:22
  • It should return whichever value the property `property` has without entering an infinite loop and without having to change the name of the property or the name of the get and set to something different (like `_property`) to avoid this loop. – Shadow May 08 '17 at 06:46
  • Then you want a simple data property instead of getters or setters. Just omit the second and third line. `var o = { property(test) { return "test"; } }; o.test();` – Bergi May 08 '17 at 06:52
  • @Bergi No, I want what I showed in the example because I want to modify the property value when it is assigned or read. – Shadow May 08 '17 at 06:57
  • You didn't say that and your code didn't do that. No, in that case there's no way around `_property` or a closure variable. – Bergi May 08 '17 at 06:58
  • @Bergi I clearly said `(...) but I would like to not do this and keep the property name intact for the object, getter and setter.` – Shadow May 08 '17 at 07:00
  • You didn't say that you "*want to modify the property value when it is assigned or read*". But Ovidiu's answer resolved the issue I guess. – Bergi May 08 '17 at 07:02
  • I also did not say `I do not want to modify the property value when it is assigned or read`, but some people just refuse to admit making a mistake, I guess. – Shadow May 08 '17 at 07:09

1 Answers1

1

A property of an object can also refer to a function or a getter or setter method.

A bit confusing but notice the OR. What was meant here is that you can have properties of an object that refer to a function OR you could have properties of an object that refer to getter/setters.

Getter/setters are simply functions that respect a specific signature and that act as an attribute with additional functionality that can be registered when setting/getting those attributes.

Typically these are used simply for calculated values, that are based on other state attributes of the object.

However, in some cases indeed you could use them to add some functionality / pre-calculations when for example setting a value.

You can do this in many ways, but if you'll still need to have a getter/setter name different than all other attributes on your object.

So for example having something like this

var o = {
  prop: 0.6
}

If you want to add something like having access to a percentage-like value, you can do:

var o = {
  prop: 0.6,
  get propPerc() { return this.prop * 100; },
  set propPerc(val) { this.prop = this.val / 100; }
}

But if you want so simply enhance the setting/getting of the prop (for example ensuring you have a numeric value always), you need to do something like:

var o = {
  _prop: 0.6,
  get prop() { return this._prop || 0; },
  set prop(val) { this._prop = this.val || 0; }
}

You need a different name for the attribute than the get/set property. For the outside unfortunately both properties will be visible, so if you use this approach it's a matter of convention to not use _prop directly, because JS doesn't have private attributes per se.

However, you can simulate something like a private attribute using symbols, for example:

var propSymbol = Symbol('prop');

var o = {
  get prop() { return this[propSymbol] || 0; },
  set prop(val) { this[propSymbol] = this.val || 0; }
}
o[propSymbol] = 0.6; // can only do it here, assuming this piece of code is not accessible to outside and propSymbol is just a local variable.

Hope this helps.

Ovidiu Dolha
  • 5,335
  • 1
  • 21
  • 30
  • I see, so my own solution was the right way of doing what I wanted all along, there is no way around the same name problem if I want to use getters and setters. – Shadow May 08 '17 at 06:58