Maybe we need a reflect API to iterate over instance members

# Gray Zhang (9 years ago)

Since class’s members are non-enumerable by default (which is a good choice) we cannot use for .. in to iterate over all members of an instance, the same problem could exists in a plain object when we use Object.defineProperty API.

In real world there are some scenarios where we need to iterate over members, A common example is we need to find all set{SomeThing} methods so we can do an auto dependency injection.

Certainly we can write a 3rd-party function to find all members through prototype chain:

function getAllMembersKeys(obj) { let keys = [];

while (obj) {
    keys.push(...Object.getOwnPropertyNames(obj));
    obj = Object.getPrototypeOf(obj);
}
 
return keys;

} But it doesn’t look nice and lacks considerations of many things such as Symbol’d keys.

Look around other languages with reflection API, most of them would provide a method to iterate over all members / properties / methods of an instance, so why not we provide a set of utility API:

Reflect.getAllMembersNames Reflect.getAllMemberDescriptors Reflect.getAllMethodNames Reflect.getAllMethodDescriptors Reflect.getAllPropertyNames Reflect.getAllPropertyDescriptors

Best

Gray Zhang

# Jordan Harband (9 years ago)

Would Reflect.ownKeys or Reflect.enumerate help you here?

# Gray Zhang (9 years ago)

Not exactly

Reflect.ownKeys does not walk up prototype chain so it does not return inherited members Reflect.enumerate seems not return non-enumerable members What I propose is an API that returns both non-enumerable and inherited members

Best

Gray Zhang

在 2015年6月1日 上午1:15:58, Zhang,Lili(PAPE) (zhanglili01 at baidu.com) 写到:

Not exactly

Reflect.ownKeys does not walk up prototype chain so it does not return inherited members Reflect.enumerate seems not return non-enumerable members What I propose is an API that returns both non-enumerable and inherited members

UBFT 张立理 Hi int08h ☎ 18621600455

在 2015年6月1日 上午12:44:52, Harband Jordan (ljharb at gmail.com) 写到:

Would Reflect.ownKeys or Reflect.enumerate help you here?

On Sun, May 31, 2015 at 4:42 AM, Gray Zhang <otakustay at icloud.com> wrote:

Since class’s members are non-enumerable by default (which is a good choice) we cannot use for .. in to iterate over all members of an instance, the same problem could exists in a plain object when we use Object.defineProperty API.

In real world there are some scenarios where we need to iterate over members, A common example is we need to find all set{SomeThing} methods so we can do an auto dependency injection.

Certainly we can write a 3rd-party function to find all members through prototype chain:

function getAllMembersKeys(obj) { let keys = [];

while (obj) {
    keys.push(...Object.getOwnPropertyNames(obj));
    obj = Object.getPrototypeOf(obj);
}
   
return keys;

}

But it doesn’t look nice and lacks considerations of many things such as Symbol’d keys.

Look around other languages with reflection API, most of them would provide a method to iterate over all members / properties / methods of an instance, so why not we provide a set of utility API:

Reflect.getAllMembersNames Reflect.getAllMemberDescriptors Reflect.getAllMethodNames Reflect.getAllMethodDescriptors Reflect.getAllPropertyNames Reflect.getAllPropertyDescriptors

Best

Gray Zhang

# Steve Fink (9 years ago)

Forgive me for golfing it, but

function getAllPropertyNames(o) { if (!o) return []; return Object.getOwnPropertyNames(o) + getAllPropertyNames(Object.getPrototypeOf(o)); }

or as a generator

function* allPropertyNames(o) { if (!o) return; yield* Object.getOwnPropertyNames(o); yield* allPropertyNames(Object.getPrototypeOf(o)); }

don't seem too onerous.

Though on the other hand, didn't I hear that prototype loops are now possible with Proxies? If so, then you'd need to handle that.

Then again, if you're going to handle weird cases, then what should it even return if you go through a Proxy's getPrototypeOf trap that mutates the set of properties?

# Gray Zhang (9 years ago)

Sorry but still not exact, the use of Object.getOwnPropertyNames through prototype chain can result in duplicate keys in override cases, so if we implement this API ourself it could be quite complex (involving a Map to filter duplicated keys)

I’m just wondering is there any reason that Reflect API is not suitable to provide such functionality?

Best

Gray Zhang

在 2015年6月1日 下午12:52:26, Fink Steve (sphink at gmail.com) 写到:

Forgive me for golfing it, but

function getAllPropertyNames(o) {     if (!o) return [];     return Object.getOwnPropertyNames(o) + getAllPropertyNames(Object.getPrototypeOf(o)); }

or as a generator

function* allPropertyNames(o) {     if (!o) return;     yield* Object.getOwnPropertyNames(o);     yield* allPropertyNames(Object.getPrototypeOf(o)); }

don't seem too onerous.

Though on the other hand, didn't I hear that prototype loops are now possible with Proxies? If so, then you'd need to handle that.

Then again, if you're going to handle weird cases, then what should it even return if you go through a Proxy's getPrototypeOf trap that mutates the set of properties?

On 05/31/2015 04:42 AM, Gray Zhang wrote: Since class’s members are non-enumerable by default (which is a good choice) we cannot use for .. in to iterate over all members of an instance, the same problem could exists in a plain object when we use Object.defineProperty API.

In real world there are some scenarios where we need to iterate over members, A common example is we need to find all set{SomeThing} methods so we can do an auto dependency injection.

Certainly we can write a 3rd-party function to find all members through prototype chain:

function getAllMembersKeys(obj) { let keys = [];

while (obj) {
    keys.push(...Object.getOwnPropertyNames(obj));
    obj = Object.getPrototypeOf(obj);
}
  
return keys;

}

But it doesn’t look nice and lacks considerations of many things such as Symbol’d keys.

Look around other languages with reflection API, most of them would provide a method to iterate over all members / properties / methods of an instance, so why not we provide a set of utility API:

Reflect.getAllMembersNames Reflect.getAllMemberDescriptors Reflect.getAllMethodNames Reflect.getAllMethodDescriptors Reflect.getAllPropertyNames Reflect.getAllPropertyDescriptors

Best

Gray Zhang

# Domenic Denicola (9 years ago)

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Gray Zhang

I’m just wondering is there any reason that Reflect API is not suitable to provide such functionality?

Reflect currently contains only methods which correspond to proxy traps. There has been talk of extending it beyond that, but making that first step is going to be a hurdle for whoever’s proposing it to extend it. A better place for such methods might be Object.* or some new module or global.

However, in the end, what you need to do to get something into the language is to prove that it's a common enough need that it's worth adding complexity to the spec and implementations. This thread is very far from doing that. A better start would be surveying open-source code to find usages of this kind of functionality.

# Brendan Eich (9 years ago)

Domenic Denicola wrote:

However, in the end, what you need to do to get something into the language is to prove that it's a common enough need that it's worth adding complexity to the spec and implementations. This thread is very far from doing that. A better start would be surveying open-source code to find usages of this kind of functionality.

Bingo. "Proof" is a convincing argument, really an empircal study of some not-too-small N samples. Kevin Smith's analysis of => utility based

on cases where functions are verbose and do or do not want this bound, taking into account concise methods from ES6, is a good example.

# Tom Van Cutsem (9 years ago)

2015-06-01 8:38 GMT+02:00 Domenic Denicola <d at domenic.me>:

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Gray Zhang

I’m just wondering is there any reason that Reflect API is not suitable to provide such functionality?

Reflect currently contains only methods which correspond to proxy traps. There has been talk of extending it beyond that, but making that first step is going to be a hurdle for whoever’s proposing it to extend it.

Or since Proxy traps correspond 1-to-1 to the "internal methods" in the spec, the primary goal of the Reflect API was to expose the essential methods that make up Javascript's object model as defined by the spec. There are many utility methods one may want to add on top, but it seems better to wait and see what the community comes up with rather than to try to codify an extensive API before it has seen any significant use.

Regarding duplicates: ES6 has Sets. It should be fairly straightforward to adapt the above example to de-dup inherited property names.

, Tom

# Alexander Jones (9 years ago)

On Monday, June 1, 2015, Tom Van Cutsem <tomvc.be at gmail.com> wrote:

2015-06-01 8:38 GMT+02:00 Domenic Denicola <d at domenic.me <javascript:_e(%7B%7D,'cvml','d at domenic.me');>>:

From: es-discuss [mailto:es-discuss-bounces at mozilla.org <javascript:_e(%7B%7D,'cvml','es-discuss-bounces at mozilla.org');>] On Behalf Of Gray Zhang

I’m just wondering is there any reason that Reflect API is not suitable to provide such functionality?

Reflect currently contains only methods which correspond to proxy traps. There has been talk of extending it beyond that, but making that first step is going to be a hurdle for whoever’s proposing it to extend it.

Or since Proxy traps correspond 1-to-1 to the "internal methods" in the spec, the primary goal of the Reflect API was to expose the essential methods that make up Javascript's object model as defined by the spec.

I like this definition. Is it written down? (I need ammunition for Reflect.type(x)!)

# Brendan Eich (9 years ago)

Alexander Jones wrote:

Or since Proxy traps correspond 1-to-1 to the "internal methods"
in the spec, the primary goal of the Reflect API was to expose the
essential methods that make up Javascript's object model as
defined by the spec.

I like this definition. Is it written down? (I need ammunition for Reflect.type(x)!)

You have my axe!

# Tom Van Cutsem (9 years ago)

2015-06-01 20:36 GMT+02:00 Alexander Jones <alex at weej.com>:

On Monday, June 1, 2015, Tom Van Cutsem <tomvc.be at gmail.com> wrote:

Or since Proxy traps correspond 1-to-1 to the "internal methods" in the spec, the primary goal of the Reflect API was to expose the essential methods that make up Javascript's object model as defined by the spec.

I like this definition. Is it written down? (I need ammunition for Reflect.type(x)!)

There's some rationale on the original wiki page for the reflect API: < harmony:reflect_api#purpose>.

We also had a related short debate on this list 3 months ago, see < esdiscuss.org/topic/reflect-getownpropertysymbols#content-0>, in

particular, Allen's comment: "In ES6, the primary role of the Reflect object is to provide direct access to an object's essential internal methods".

, Tom