0
person = {
id: 1,
name: 'John',
phone: '123-456-789',
getSetGen: function(){

for(var key in this){
    this[`set${key}`]=function(value){
        this[key] = value;
        console.log(this[key]);
    }

    this[`get${key}`]=function(){
        console.log(this[key]);
        return this[key];
    }
    

// for(key in this){
//     console.log(this[key]);
//     if(key!='getSetGen'){
//         Object.defineProperty(this, `Set${key}`, {
//             set : function (value) {
//                 this[key] = value;
//             }
//         });

//         Object.defineProperty(self, `Get${key}`, {
//             get : function () {
//                 return this.key;
//             }
//         });
//     }
// }
}
}



person.getSetGen()

person.getname();

I am trying to make a function property to generate getters and setters for the object and can used with other object.

After running the code above the setter and getter is not working, just carrying the functions as 'this[key]' not the actual properties and object

Lzh
  • 3,585
  • 1
  • 22
  • 36
IBdr
  • 1
  • 2
  • 2
    Let's start with the why. Why do you need these "getters/setters" if all they do is forward the operation to the property itself. Why not just use the property? And in your code you mix two approaches, proper getter/setter that "look" like regular properties, and are accessed like them. And get/set *methods*, which are called like, well like methods. Which one do you want? – Thomas Aug 29 '22 at 22:03
  • this is just a simulation for what it can do, but if I want to make the property a private, I will need the setter and getter. For the second reason, generating setter and getter will allow to make object with public property to object with private property and use the setter and getter instead. – IBdr Aug 29 '22 at 22:11
  • 1
    long story short: I assume you come from a different programming language? Through how many loops are you willing to jump, and how much of a performance impact are you willing to take just so that you can have private properties? Yes JS has gotten private fields recently, and before that we've simulated them with closures, but for the most part it's not worth it. I still think that privacy by convention is the better choice. – Thomas Aug 29 '22 at 22:19
  • Originally, this is the purpose of setter and getter. Furthermore, if I want to add some code to the setter and getter before adding the property and doing this without affecting the rest of the code, I can do this by the setter and getter function. – IBdr Aug 29 '22 at 22:30
  • I think I found your problem. `for(var key in this)` is not block-scoped *(and `for(key in this)` is even a global variable)*, so all your methods point to the same (the last) `key` that you iterated over. here: [What is the difference between "let" and "var"?](https://stackoverflow.com/questions/762011/what-is-the-difference-between-let-and-var). use `for(const key in this)` – Thomas Aug 29 '22 at 22:49
  • I changed it and now the code is working. Thank you very much. – IBdr Aug 29 '22 at 22:54
  • Good old `var` never disappoints – Konrad Aug 29 '22 at 22:55
  • @KonradLinkowski I can't agree more – IBdr Aug 29 '22 at 23:01

1 Answers1

2

Edit (now that I understand OP's intention)

Defining properties that wrap existing fields on an object.

  1. Go through the fields
  2. Use the field names to add a single property for each field.

Like this, see the comments in the code:

let myObj = {
    id: 1,
    name: 'tomato',
};

for(let fieldName of Object.keys(myObj)) {
    console.log(`fieldName = ${fieldName}`);
    Object.defineProperty(myObj, fieldName + "_property", {
        set: function(value) {
            this[fieldName] = value;
        },
        get: function() {
            return this[fieldName];
        }
    });
}

myObj.id_property = 55; // setting id_property will set id
console.log(myObj.id); // so this will write 55

myObj.id = 123; // setting id
console.log(myObj.id_property); // this will write 123 because id_property returns id field

[Obsolete("Previous answer")]

Before trying a generic approach to defining properties, let's try to define a normal static property. For example here is code for property called Xyz on some object called myObj.

As you can see, you can define the getter and setter in a single call to defineProperty.

var myObj = {};
Object.defineProperty(myObj, `Xyz`, {
    set: function (value) {
        this['_Xyz'] = value;
    },
    get: function() {
        return this._Xyz;
    }
});

Also notice that I'm using a "backing field" called _Xyz here.

So to make things generic, we want to define a property called "Something" and use a backing field called "_Something".

You can easily then create a loop for this.

Then when you run the loop you can access properties like the above like this:

myObj.Xyz = 1; console.log(myObj.Xyz); // writes 1


Also notice that when you set and get a property, you do NOT use parentheses. E.g. myObj.myProperty() is NOT correct. Conventionally, we also don't add get or set prefixes to the name of the property. We just say myProperty and not getMyProperty.

Lzh
  • 3,585
  • 1
  • 22
  • 36
  • I don't get the point of defining new properties. the problem here is to get and set value for existing property through the setter and getter functions. In other words "this[_Xyz] = value", the _Xyz should be an existing property not new one – IBdr Aug 29 '22 at 22:19
  • @IBdr but didn't you do the same thing, creating a **new field** `this[\`set${key}\`]` as a setter for a (private) backing field `this[key]`. – Thomas Aug 29 '22 at 22:24
  • Yes, the new field is for the setter and the getter methods, not a new property. Like in my code, I have 'id' property, I will use the setter to change its value, not to add a new property – IBdr Aug 29 '22 at 22:33
  • @IBdr That's not possible. You either have a data property storing a value or an accessor property with getter/setter functions (that need to store the value elsewhere, be it another property or a local variable), you cannot have both at once with the same property name. – Bergi Aug 30 '22 at 01:12
  • @IBdr I'm not sure why you want to wrap the fields with properties, maybe you want them to execute code other than just set/get a value when they are accessed... Anyways, I updated my answer with what you wanted, see the example and code comments – Lzh Aug 30 '22 at 08:20