Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate over all properties in object's prototype chain?

I have an es6-class instance and I need to get all its properties (and inherited properties too). Is there a way to do this without traversing prototype chain?

class A {
  get a() {
    return 123;
  }
}

class B extends A {
  get b() {
    return 456; 
  }
}

const b = new B();

for (let prop in b) {
  console.log(prop); //nothing
}

console.log(Object.keys(b)); //empty array
console.log(Object.getOwnPropertyNames(b)); //empty array
console.log(Reflect.ownKeys(b)); //empty array
console.log(Object.keys(Object.getPrototypeOf(b))); //empty array
console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(b))); //["contructor", "b"] -- without "a"
console.log(Reflect.ownKeys(Object.getPrototypeOf(b))); //["contructor", "b"] -- without "a"
like image 526
Digger2000 Avatar asked Oct 18 '16 07:10

Digger2000


1 Answers

...(and inherited properties too). Is there a way to do this without traversing prototype chain?

Not if they're non-enumerable, as your b property is. To enumerate non-enumerable properties (!), you have to use getOwnPropertyNames (and getOwnPropertySymbols), and to include inherited ones, you have to loop through the prototype chain.

Which isn't a problem:

class A {
    get a() {
        return 123;
    }
}

class B extends A {
    get b() {
        return 456; 
    }
}

const b = new B();

let allNames = new Set();
for (let o = b; o && o != Object.prototype; o = Object.getPrototypeOf(o)) {
    for (let name of Object.getOwnPropertyNames(o)) {
        allNames.add(name);
    }
}
console.log(Array.from(allNames));

Note that I assumed you wanted to skip the ones on Object.prototype like toString, hasOwnProperty, and such. If you want to include those, change the loop condition to o != null (or just o if you like that sort of thing).

like image 110
T.J. Crowder Avatar answered Oct 14 '22 16:10

T.J. Crowder