DavidT
DavidT

Reputation: 777

javascript getter and setter within object property within class

As we know, getters and setters are basically functions that allow for computed properties while maintaining the simplicity of accessing them like properties instead of methods/functions.

It may or may not be relevant that I've particularly found this useful with the new private class members.

Example:

class A {
    #a;
    constructor() {
        this.#a = "something";
    }
    get a() {
        // do some stuff that a depends on a...
        // ... and then ultimately return it: 
        return this.#a;
    }
    set a(arg) {
        // do some stuff that depends on a or vice versa...
        // ... and then ultimately set a to something: 
        this.#a = something();
    }
}

Of course it looks like two "functions" but I access it as a property:

const aObj = new A();
console.log(aObj.a);  // runs the getter
aObj.a = "x"; // runs the setter

So now... I'm trying get that same functionality, but where a (and a bunch of other properties) are not always loose on the top level of the class, but some of them be properties within object definitions inside the class. Something like:

class B {
    #innerObjProp;
    constructor() {
        this.#innerObjProp = {};
        this.#innerObjProp.b = "b";
    }
    get this.#innerObjProp.b() {
        // do some stuff that b depends on...
        // ... and then ultimately return it: 
        return this.#innerObjProp.b;
    }
    set this.#innerObjProp.b(arg) {
        // do some stuff that depends on b or vice versa...
        // ... and then ultimately set b to something:
        this.#innerObjProp.b = something();
    }
}

To my knowledge (and according to my IDE) that get and set above is not correct syntax, but hopefully it illustrates what I'm trying to do.

(#innerObjProp and #a are private in these examples, which is desired in my current case, but that's not key to the question. Presumably if there's a way to do this, it's the same for both private and public properties.)

Can anyone tell me please if this is possible, and how?

Thanks in advance for help!


2 hours later, update. A couple of code corrections above. Plus, feeling a need to clarify a couple of things based on questions in the comments:

TL;DR, short version: I'm looking for something that conceptually is:

this.#innerObjProp.(get b(){ 
    return ... ;
});
this.#innerObjProp.(get c(){ 
    return ... ;
});

I realize that's not correct syntax but I can't find anywhere that shows what it should be.


More detail. Skip this if the above is clear enough:

My node command line app is connected to an API that's streaming consistently updated data. I have access to 2 or 3 large API objects with everything I need in them, constantly being updated. At any moment I have the latest data but it's changing frequently (some more than 1/sec). I don't need write access to any of it, only read. It absolutely needs to be organized differently for my app than it's being delivered to me or my code will be an organizational nightmare.

So my classes, some static some instantiated, are collections of read only properties, needing to be derived on the fly. I have a couple of classes that are doing almost nothing but rearranging it all and handing bits out to the rest of the app as needed.

It seems to me that a getter is a great option for each of these, each with the name my app would prefer, reading on the fly from the API object(s), making some adjustments (they're derived calculated properties) and delivering that result to whatever else in my app that asked for it.

Until I figure this out I'm just organizing all these properties at their classes' top levels, but I'd much prefer to group some of them together. That's where things like innerObjProp comes in.

Finally, I need to use some of the properties in a couple of the groups before I have access to all of them. Therefore, thanks to @Bergi below, this.#innerObjProp = { get ...(), get...(), get...()} works at first but I can't figure out the syntax for adding another getter to it later in the code like I can with an ordinary property eg. this.#innerObjProp.c = ....

Upvotes: 0

Views: 3226

Answers (1)

Bergi
Bergi

Reputation: 665448

I'm trying to do is get that same functionality, but where the property is not loose on the top level of the class, but within an object property inside the class.

Then you need to create that object somewhere first. As you will want to have a separate object (with different property values) for each instance, create that instance-specific object in the constructor:

class B {
    #innerObjProp;
    constructor() {
        this.#innerObjProp = {};
    }
}

and then define your getters/setters in that object, not on the class level, with the usual ES5 syntax for getters/setters in object literals:

class B {
    #innerObjProp;
    constructor() {
        let b = "b"; // a local variable as a place to store the value
        this.#innerObjProp = {
            get b() {
                // do some stuff that b depends on...
                // ...
                // ... and then ultimately return it: 
                return b;
            },
            set b(arg) {
                // do some stuff that depends on b or vice versa...
                // ...
                // ... and then ultimately set b to something:
                b = something();
            }
        };
    }
}

Notice that this is a code smell. If your class has grown so large that you don't want to put some things at its "top level", something is wrong with your design, and you should consider splitting the class into multiple smaller classes.

Upvotes: 2

Related Questions