0

I want to use the fact the getter of an object property can be overridden. In attempting to find the right syntax, I ran into trouble where using the following syntax works, but the syntax below it and the bit at the bottom, my preferred method, do not.

I'd like to avoid using Object.prototype and to generalize this to function and class objects. There is no difference if the javascript object is instantiated with the literal or stipped of its proto using the Object.create(null) method.

To invoke the setter, boo['bar'] = 'some value' throws an error: call stack limit exceeded. The same happens if the string value returned by get is replaced with return this.bar and the setter is invoked. The setter otherwise appears to work as advertised, the caveat being the getter then has trouble. The getter also has trouble when trying to concatenate return this.bar + 'some string' which makes me grasp at what the restrictions with this approach are?

// const boo = Object.create(null) // javascript object... no
const boo = function(){} // a function is an object
let bar = 'bar'
let count = 0
Object.defineProperty(boo, bar, {
   get: function() {
           return `${count++}` + ' function-derived values, too, but now: ' + this._bar
           // bar is not the property on which the value is stored
           
   },
   set: function(value) { this._bar = value },
   configurable: true,
   writeable: true,
   enumerable: true 
})

console.log(boo.bar)
// get or set, but not both on javascript objects. functions and classes, sure...
boo['bar'] = 'some value'
console.log(boo.bar)
console.log(boo._bar) // disappointing...

The code below demonstrates the problem. Is the syntax as presented a lost cause where having the getter override return this.key, the apparent default is concerned?

So, why isn't the getter overridden using this and other syntax where Object.defineProperty() is inside another function?

const ob = {}

    function defPropA(object, key, valDefault){
        // do some limited things...
        // for..in loop over same object to set array of properties on it
        
        Object.defineProperty(object, key, {
            get: function() {return 'no joy'}, //{return this[key + '_']},
            set: function(value) {
                if (this[key + '_'] !== undefined){
                    console.log(`"${this[key + '_']}" changed to: "${value}"`)
                }
                    this[key + '_'] = value
            },
            configurable: true,
            writeable: true,
            enumerable: true
        })
        object[key] = valDefault
        // recurse defPropA for some reason, maybe map of objects with properties (many/many)
    }
    
    let checkObj = (object, key) => {
        console.log(object[key]) // computed value
        object[key] = 'it\'s a set up'
        console.log(object.key) //<--- where my mistake lives

  //... wherever a key is passed as a parameter
  // you must use 'array' syntax to simulate dot syntax
  // because the string must be calculated/retrieved from its bound name...
  // ...

    }
    
    defPropA(ob, 'propX', 'key default value')
    checkObj(ob, 'propX')

By 'other' I mean something like this:

function makeObjProp(object, key, value){
    const config = {
        get: function() {return this.key},
        set(value) {this.key = value},
        ... etc
    }
    Object.defineProperty(object, key, config)
}
Tim Pozza
  • 498
  • 6
  • 9
  • 2
    I really don't get what you are asking about, and whether your code snippets are working as expected or not. But it might still be helpful to know: `this.key` is not the same as `this[key]`, a property can only be either an accessor (getter/setter) or a data property, not both - so you cannot have a `writable` option on an accessor, and you have to store the underlying data somewhere else since an access to the same property is indeed just a recursive call. – Bergi Aug 18 '19 at 21:09
  • 1
    Neither do I... The problem with snippet #2 is indeed that you define special handling for `ob["propX"]`, but access `ob["key"]`. – Nickolay Aug 18 '19 at 23:13
  • To me, it looks like the logging function inside the getter doesn't kick off, so the value being returned is from a default getter... Is it something I misunderstand; thinking the getter as re-defined should work, overriding what's on the prototype? How is a value returned otherwise? And, maybe, how to know or identify the internal [[slot]], assuming it has a special name? – Tim Pozza Aug 19 '19 at 05:26

0 Answers0