yogmk
yogmk

Reputation: 185

JavaScript: get & set nested attributes of an object

There are questions and answers on how to get & set nested attributes/properties on an object in JS around the net & StackOverflow as well, but none so far fit my problem, so here it is.

The code that declares/defines the object is

/**
 * a dummy class for experiments
 */

module.exports = function() {
  this.Delme = () => {
    const attrs = {
      name: '',
      age: '',
      addr: {
        street: '',
        city: '',
        pin: ''
      }
    };

    return Object.create({
      set(name, value) {
        if (attrs.hasOwnProperty(name)) {
          console.log(`setting attrs.${name} to ${value}`);
          attrs[name] = value;
          return true;
        } else {
          console.log(`Object has no property named ${name}`);
          return false;
        }
      },

      get(name) {
        if (attrs.hasOwnProperty(name)) {
          return attrs[name];
        } else if (attrs.addr.hasOwnProperty(name)) {
          return attrs.addr[name];
        } else {
          return null
        }
      }
    });
  };
};

/**
 * Based on some other posts I wrote this anyway, 
 * but I'm not sure how to use this in my object creation.
 * 
 * function() returning an 'addr' object
 */

const Address = function() {
  const _addr = {
    street: '',
    city: '',
    pin: ''
  };

  return Object.create({
    set(name, value) {

      if (_addr.hasOwnProperty(name)) {
        console.log(`setting _addr.${name} to ${value}`);
        _addr[name] = value;
        return true;
      } else {
        console.log(`Object has no property named ${name}`);
        return false;
      }

    },

    get(name) {
      return _addr[name];
    }
  });
}
// Above function is currently not used

And here is the code that I used to test the object creation

require('../lib/delme')();

const personFactory = function (target) {
    return Delme.call(target);
} ;

const george = { name: 'george' };
const person = personFactory(george);

//person.on('change', data => console.log(data));

person.set('name', 'Sam');
console.log(person.get('name'));

person.set('unknown', 'anything');
console.log(person.get('unknown'));

console.log(person.hasOwnProperty('name'));

const person9 = personFactory({name: 'Charlie', age :'27'});
console.log(person9.get('name'));
console.log(person9.set('age', '42'));
console.log(person9.get('age'));

person9.set('addr', {street:'main road', city:'somewhere', pin:'560032'});
//console.log(person9.addr.city)
console.log(person9.get('city'));

person9.set('addr[street]', '3rd Lane')
console.log(person9.get('street'));

The output is

setting attrs.name to Sam
Sam
Object has no property named unknown
null
false

setting attrs.age to 42
true
42
setting attrs.addr to [object Object]
somewhere
Object has no property named addr[street]
main road

Q.1 : How do I properly get() & set() nested attributes. I wish to be able to person.get('addr.street') and person.set('addr.pin', '123456'). Currently I can only set the entire addr object by passing it during object creation.

Q2. How can I enable my class to emit events, so that I can code like person.on('change', data => console.log(data));

Upvotes: 1

Views: 241

Answers (1)

Abdulaziz Alaboudi
Abdulaziz Alaboudi

Reputation: 61

I would advise you to use ES6 class syntax rather than the prototype and implement set and get as methods. For question 2, there is no easy way to do that. You can manually implement that using a library such as pubsub-js to emit events inside the set and get methods.

Upvotes: 1

Related Questions