0

The following constructor function is written in JavaScript / ES5 -

function Range(from, to) {

    function getFrom() { return from; }
    function getTo() { return to; }

    function setFrom(f) { from = f; }
    function setTo(t) { to = t; }

    Object.defineProperties(this, {
        fromProp: { get: getFrom, set: setFrom, enumerable: true, configurable: false },
        toProp: { get: getTo, set: setTo, enumerable: true, configurable: false }
    });
};

I create an object using this constructor as follows -

var range = new Range(4, 13);  

My general understanding of object creation is, there should be some code inside the constructor that, after instantiating the object range, will initialize fromProp and toProp with the values I passed through the parameters to the constructor. But I'm having hard time understanding how exactly that is happening here.

Or, is it that the whole "initializing/accessing property" things here are captured inside the closure of setter/getter invocation? But if so, then at any time when I use -

range.fromProp = 22;

the value 22 actually never gets set to the range object's property fromProp, but rather to the parameter variable from, and then whenever I ask for -

var fromValue = range.fromProp;

it just hands me over the current value of the parameter variable from. Am I getting this right, or missing something?

Any explanation on the matter?

Cœur
  • 37,241
  • 25
  • 195
  • 267
atiyar
  • 7,762
  • 6
  • 34
  • 75
  • One of the properties of a property descriptor is `value`; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties. And I have the feeling you're making this too hard on yourself by using those getters and setters, since they don't seem to actually do anything special. – Heretic Monkey Jul 06 '18 at 03:07
  • 1
    Yes, it's all closures over the parameters. You can easily test this by e.g. closing over the parameters in another function, make that accessible outside (e.g. by setting it to a global variable for test purposes), and use that function to change the properties: `let changer; function Range(from, to) { changer = x => { from = x }; /* rest of constructor as you wrote it */ }; var range = new Range(4, 13); changer(999); console.log(range.fromProp);` – ASDFGerte Jul 06 '18 at 03:08
  • @HereticMonkey, they seem to provide a nice encapsulation over your object's internal state :) – atiyar Jul 06 '18 at 03:16
  • The code is working for me the way I expect it to, I'm not sure what you're asking. What value are you expecting `fromValue` to hold in you last line of code (`var fromValue = range.fromProp;`)? – Mark Jul 06 '18 at 03:36
  • 2
    @MarkMeyer, I didn't say that the code is not working. My question is based on "knowing the way it is working" if you understand what I mean. `fromValue` holds 22, but the thing is, it never gets that value from the `fromProp` property of `range` object, but from the `from` parameter variable of the constructor :) – atiyar Jul 06 '18 at 03:53
  • 1
    `fromProp` is not a data property, it's an [accessor property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#Description). The [property accessor operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors) (in this case the `.` in `range.fromProp`, not to be confused with with an accessor property) invokes the accessor property's getter function which resolves the value from the scoped access to the `from` parameter in the constructor. – Patrick Roberts Jul 06 '18 at 04:19

2 Answers2

0
function Range(from, to) {

function getFrom() { return from; }
function getTo() { return to; }

function setFrom(f) { from = f; }
function setTo(t) { to = t; }

Object.defineProperties(this, {
    fromProp: { get: getFrom, set: setFrom, enumerable: true, configurable: false },
    toProp: { get: getTo, set: setTo, enumerable: true, configurable: false }
});

};

Lets analyse here , you are setting the "get" property of "fromProp" as the reference of "getFrom" function where you are returning the value of "from" param and in the same way the "set" is referencing the function "setFrom" where the assignment of value to "from" is being done.

As the conclusion the get and set of fromProp is not directly holding the value rather it is holding the accessor function to return the value of "from".

Hope your doubt is clear now.

Anubrij Chandra
  • 1,592
  • 2
  • 14
  • 22
0

If you are from a Java/C# world, then this of course seems a bit odd at first look, because in those languages any values passed through the constructor parameters are typically used to initialize the object, i.e. saving the values as the object's internal state, which are usually represented with private fields. Then those private fields are exposed to the outside world via properties with getter/setter.

So, the getter/setter in those languages actually encapsulate the object's internal data, not the constructor parameters.

JavaScript on the other hand does not provide the ability to make it's object's state private.

That's why the values of the constructor parameters here have not been saved to any data properties, and rather, are captured in Closure of invocation of the accessor properties (as mentioned in the comments), to simulate the object's private state.

atiyar
  • 7,762
  • 6
  • 34
  • 75