Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to distinguish between a getter and a setter and a plain property in JavaScript?

Tags:

javascript

How can I programmatically identify getter and setter properties in ES5?

var o, descriptor, descriptorGetter, descriptorSetter;

o = { 
  foo: 'foo',
  get bar() {
    return 'bar';
  },
  set bam(value) {
    this._bam = value;
  },
};

descriptor = Object.getOwnPropertyDescriptor(o, 'foo');
descriptorGetter = Object.getOwnPropertyDescriptor(o, 'bar');
descriptorSetter = Object.getOwnPropertyDescriptor(o, 'bam');

console.log(JSON.stringify(descriptor));
console.log(JSON.stringify(descriptorGetter));
console.log(JSON.stringify(descriptorSetter));

Prints:

{"value":"foo","writable":true,"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
like image 688
Ben Aston Avatar asked Jun 09 '15 20:06

Ben Aston


1 Answers

When you are stringifying, you will lose all the undefined and the Function objects. Instead, you can check if the returned property descriptor object has a non-undefined get or set properties and decide like this

  1. If the property descriptor has a value property, it is a normal data property.

  2. If the property descriptor has get and set properties, and both have functions as values, then it is an accessor property.

  3. If the property descriptor has get's value as a function, then it is a getter property.

  4. Otherwise, a setter property.


Since value is there, it is a normal data property:

descriptor.hasOwnProperty('value');
// true

Here, value is not there, but get property is a function. So a getter property:

descriptorGetter.hasOwnProperty('value');
// false
typeof descriptorGetter.get === 'function';
// true
typeof descriptorGetter.set === 'function';
// false

Here also, value is not there, but set property is a function. So a setter property:

descriptorSetter.hasOwnProperty('value');
// false
typeof descriptorSetter.get === 'function';
// false
typeof descriptorSetter.set === 'function';
// true

Apart from that, if you had an accessor property, like this

var o = {
    get cabbage() {
        return 'cabbage';
    },
    set cabbage(value) {
        this._cabbage = value;
    },
};

descriptorCabbage = Object.getOwnPropertyDescriptor(o, 'cabbage');

console.log(descriptorCabbage.hasOwnProperty('value'));
// false
console.log(typeof descriptorCabbage.get === 'function');
// true
console.log(typeof descriptorCabbage.set === 'function');
// true

You can write this as a function, like this

function getTypeOfProperty(object, property) {
    var desc = Object.getOwnPropertyDescriptor(object, property);

    if (desc.hasOwnProperty('value')) {
        return 'data';
    }

    if (typeof desc.get === 'function' && typeof desc.set === 'function') {
        return 'accessor';
    }

    return typeof desc.get === 'function' ? 'getter' : 'setter';
}

console.log(getTypeOfProperty(o, 'foo'));
// data
console.log(getTypeOfProperty(o, 'bar'));
// getter
console.log(getTypeOfProperty(o, 'bam'));
// setter
console.log(getTypeOfProperty(o, 'cabbage'));
// accessor
like image 97
thefourtheye Avatar answered Sep 17 '22 21:09

thefourtheye