Shnick
Shnick

Reputation: 1391

How to easily get non-getter properties from an object

I have an object which looks like so:

const obj = {
  x: 1,
  y: 2,
  foo() {
    return "foo";
  },
  get bar() {
    return "bar";
  }
}

For simplicity, this object only has one getter method, however, other objects can have even more getters.

Is there a simple way to get the properties of an object such that it excludes all functions, as well as all getter method(s)?

My desired result is:

const properties = ["x", "y"];

I tried looking into using Object.keys(), however this gives all properties, including all methods. I also tried looking into Object.getOwnPropertyNames(), however, this still includes all function names in the result.

Please Note: I am aware that I can filter out the getters from the result of getOwnPropertyNames() by maintaining my own set of the getters somewhere and check if the property is included in that set. However, this doesn't seem like a very good solution to me as there will a dependency between the set and the object's properties. I am also aware that I can set the method's enumerable attribute to false. However, this would require me to scan through all the methods within my object and manually do this. Is there an easier way which could perhaps do this automatically to achieve the desired result?

Upvotes: 2

Views: 1134

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370819

Use Object.getOwnPropertyDescriptors to get an object with the same keys, whose values are descriptors. Use Object.entries to turn the object into an array, .filter to filter for descriptors with .values (data descriptors only; accessor descriptors, like those with getters, don't have .values) and make sure the value isn't a function either. Then .map to their keys:

const obj = {
  x: 1,
  y: 2,
  foo() {
   return "foo";
  },
  get bar() {
    return "bar";
  }
};

const output = Object.entries(Object.getOwnPropertyDescriptors(obj))
  .filter(([, desc]) => desc.hasOwnProperty('value') && typeof desc.value !== 'function')
  .map(([key]) => key);
console.log(output);

Upvotes: 6

Related Questions