3

Is it possible to define generic getters / setters for ALL Javascript Objects?

Pseudocode of what I want to do is below. Basically, person and animal route getters and setters to CustomGetter and CustomSetter.

function NewPerson()
{
    var person;
    var animal;

    var person.name = 'John Doe';
    console.log("Name: " + person.name); //Prints "Name: JOHNDOE CUSTOM"

    var animal.type = 'Herbivore';
    console.log("Animal: " + animal.type); //Prints "Animal: HERBIVORE CUSTOM"

    console.log("Age: " + person.age); //Prints "Age: NON EXISTANT PROPERTY";
}

function CustomGetter(theObj, propertyName)
{
    if(theObj.hasproperty(propertyName))
        return ToUpperCase(theObj.propertyName);
    else
    {
        return "NON EXISTANT PROPERTY";
    }
}

function CustomSetter(theObj, propertyName, value)
{
    if(theObj.hasproperty(propertyName))
        theObj.propertyName = value + " CUSTOM";
    else
    {
        console.log("NON PROPERTY TO SET");
    }
}

Thank you!

Water
  • 1,114
  • 1
  • 15
  • 31
  • Have a look at Object.defineProperty: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty – Psi Feb 27 '17 at 14:34
  • 1
    There is no catch-all setter/getter for objects, you would need to wrap your object in a Proxy to get that functionality: http://stackoverflow.com/questions/7891937/is-it-possible-to-implement-dynamic-getters-setters-in-javascript – Patrick Evans Feb 27 '17 at 14:37

3 Answers3

2

I just did something like that recently. If you do defineProperty on the prototype, you can apply it to all instances. Kinda like this:

   Object.defineProperty(Object.prototype, 'test', {
        get: function () {
            return "a test";
        }
    });

var test = new Array(2);
console.log(test); //a test

Now any object will have the property 'test'.

brianxautumn
  • 1,162
  • 8
  • 21
  • 2
    Thanks. I was taking a look at it and it seems Proxy is more the answer than defineProperty. With proxy I can catch even unexisting properties. – Water Feb 28 '17 at 13:13
0

You should use proxy trap to do what you want.

Documentation: MDN - Proxy handlers

You can easily perform that with a class and prototype, but i rather using getter/setter traps from a custom handler into a closure

Typically, it can look like that:

var Person = function(profile={})
{
    var required     = ["age", "name", "profession"];
    var buildProfile = function(p)
    {
        for(var prop of required)
        {
            if(!(prop in p))
                throw new ReferenceError
                ("⛔ Missing required property to profile '" +(prop+" in "+JSON.stringify(profile))+ "'");
        }
        return p;
    }(profile);

    var anotherPrivateFunc = function()
    {
        // ...
    };

    var publicMethods = 
    {
        status: function(prop, value)
        {
            // ...
        },
        isAdult: function()
        {
            return this.age >= 18;
        },
    };

    Object.assign(profile, publicMethods);
    return new Proxy(profile,
    {
        get: function(target, prop, receiver)
        {
            if(prop in target)
            {
                switch(prop)
                {
                    case "name":
                        return target[prop].toUpperCase(); break;
                }
            }
            return Reflect.get.apply(Object.getOwnPropertyDescriptor, arguments);
        }
    });
};

var person = new Person({age:32, name: "Water", profession:"developper"})

person.name      // will return WATER
person.age       // --> 32
person.isAdult() // --> true

var person = new Person({age:32}) // will throw an cusotm error
Uncaught ReferenceError: ⛔ Missing required property to profile 'name in {"age":3}'
MTroy
  • 897
  • 9
  • 20
-1

You can create a property setter or getter using Object.defineProperty: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

From the MDN-Documentation:

Object.defineProperty(obj, 'propertyName', {
  get: function() { return bValue; },
  set: function(newValue) { bValue = newValue; },
  enumerable: true,
  configurable: true
});
Psi
  • 6,387
  • 3
  • 16
  • 26