Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Enumeration of extended properties of Array and Object prototypes

2 views
Skip to first unread message

Chris Zumbrunn

unread,
Mar 19, 2004, 10:19:06 AM3/19/04
to
I understand that in accordance with the ECMA specs both Spidermonkey
and Rhino make that additional methods added to Objects are enumerated
in Javascript for/in loops.

I know that changing this in the specs for Javascript 2.0 has been
suggested but I don't know if this is now part of the JS 2.0 proposal or
if it is being considered. Are there good reasons not to change this
behavior?

Also, for the time being... Would it be hard to patch Rhino so that
additions to the Array and Object prototypes would not get enumerated?
Has anybody already attempted or done this?

-- Chris Zumbrunn
-- ch...@deployzone.com
-- +41 329 41 41 41
-- http://www.deployzone.com/

--
Chris Zumbrunn
ch...@deployzone.com
+41 329 41 41 41
http://www.deployzone.com/ - Reduced to the Maximum!

Brendan Eich

unread,
Mar 19, 2004, 8:08:41 PM3/19/04
to Chris Zumbrunn
Chris Zumbrunn wrote:
> I understand that in accordance with the ECMA specs both Spidermonkey
> and Rhino make that additional methods added to Objects are enumerated
> in Javascript for/in loops.

What do you mean, exactly? Can you give an example?

/be

Chris Zumbrunn

unread,
Mar 19, 2004, 9:52:00 PM3/19/04
to
Brendan Eich wrote:

Array.prototype.foo = "bar";
var a = new Array(1,2,3);
for (var i in a) {x += i}

x is 123foo, but I'd want it to be 123

Brendan Eich

unread,
Mar 19, 2004, 10:00:14 PM3/19/04
to Chris Zumbrunn

ECMA dictates that it should be "123foo".

Did you mean that native code defined 'foo' as some kind of built-in? In
that case, the native code can use ECMA DontEnum, or in SpiderMonkey
terms, can not use JSPROP_ENUMERATE.

If you mean exactly what you show as an example, then there's no way any
conforming implementation can avoid enumerating 'foo'.

/be

Chris Zumbrunn

unread,
Mar 19, 2004, 10:45:56 PM3/19/04
to
Brendan Eich wrote:

> ECMA dictates that it should be "123foo".
>
> Did you mean that native code defined 'foo' as some kind of built-in? In
> that case, the native code can use ECMA DontEnum, or in SpiderMonkey
> terms, can not use JSPROP_ENUMERATE.

No, I do mean prototype properties that are defined dynamically via
Javascript.

> If you mean exactly what you show as an example, then there's no way any
> conforming implementation can avoid enumerating 'foo'.

Yes, I know that :-)

Getting back to my original question...

Is a change to this being considered for JS 2.0 (and the next ECMA
specs). Is any way being considered that would allow to add members to
objects, particularly prototype objects, without them being enumerated
by for/in loops? This could for example also be in the form...

dontenum Array.prototype.foo;

...or something of that nature, if that helps to avoid backwards
compatibility headaches.

Could the current Rhino engine be patched in any way that would allow
objects that act as collections to provide methods that act on those
collections? Has someone already attempted or done this? Or is there a
good reason why this would be a bad idea (other than breaking the specs)?

Chris

Brendan Eich

unread,
Mar 19, 2004, 11:59:34 PM3/19/04
to Chris Zumbrunn
Chris Zumbrunn wrote:

> Yes, I know that :-)

Ok, good to know -- it wasn't totally clear (maybe I was being dense)
from your original posting.

> Getting back to my original question...
>
> Is a change to this being considered for JS 2.0 (and the next ECMA
> specs). Is any way being considered that would allow to add members to
> objects, particularly prototype objects, without them being enumerated
> by for/in loops? This could for example also be in the form...
>
> dontenum Array.prototype.foo;
>
> ...or something of that nature, if that helps to avoid backwards
> compatibility headaches.

See
http://www.mozilla.org/js/language/js20/core/definitions.html#visibility-attributes.

Why do you want this, exactly? For what purpose?

/be

Chris Zumbrunn

unread,
Mar 20, 2004, 12:18:50 AM3/20/04
to
Brendan Eich wrote:

> See
> http://www.mozilla.org/js/language/js20/core/definitions.html#visibility-attri
> butes.

OK, so there will still be no way to make a user-defined dynamic or
class property non-enumerable.

> Why do you want this, exactly? For what purpose?

Hmm, I'm surpised you're asking. What's the point of being able to add
custom methods to the Object or Array prototypes if doing so will break
any application that uses for/in loops?

Chris Zumbrunn

unread,
Mar 20, 2004, 12:32:12 AM3/20/04
to
Chris Zumbrunn wrote:

> Brendan Eich wrote:
>
> > Why do you want this, exactly? For what purpose?
>
> Hmm, I'm surpised you're asking. What's the point of being able to add
> custom methods to the Object or Array prototypes if doing so will break
> any application that uses for/in loops?

Of course, I meant "any application that uses for/in loops to iterate
through objects that serve as collections".

Georg Maaß

unread,
Mar 21, 2004, 9:59:43 AM3/21/04
to
Chris Zumbrunn wrote:
> Of course, I meant "any application that uses for/in loops to iterate
> through objects that serve as collections".

Do not prototype them to create your own variation. Derivate them to
define your own variation.

--
Georg Maaß - bioshop.de D-76227 Karlsruhe, Westmarkstraße 82
HTML, XML / JavaScript, C++, Java, PHP, VB / CGI, JSP, ASP, ASP.net
- The ultimate DHTML engine: http://gml-modul.sourceforge.net -
http://sourceforge.net/projects/gml-modul

Brendan Eich

unread,
Mar 21, 2004, 2:12:05 PM3/21/04
to Chris Zumbrunn
Chris Zumbrunn wrote:
>
> OK, so there will still be no way to make a user-defined dynamic or
> class property non-enumerable.

Not unless something has changed in the ECMA working draft.

>>Why do you want this, exactly? For what purpose?
>
> Hmm, I'm surpised you're asking. What's the point of being able to add
> custom methods to the Object or Array prototypes if doing so will break
> any application that uses for/in loops?

I'm asking for a real-world example where such a loop breaks because of
the user-defined prototype property. Almost all such loops that I've
seen are inspecting/debugging loops, where the added prototype
properties can be filtered out, by script or by the reader. It's not
ideal, but it's not a fatal ("will break") situation.

An easy way for scripts to filter is to use Object.prototype.hasOwnProperty:

for (var i in o) {
if (o.hasOwnProperty(i))
print(i, o[i]);
}

It's easy to imagine for..in loops that are critical to a script, and
that would fail in light of user-defined prototype properties. But I
didn't want to imagine, I was looking for reality ;-).

/be

Brendan Eich

unread,
Mar 21, 2004, 2:14:13 PM3/21/04
to Chris Zumbrunn
Chris Zumbrunn wrote:

> Of course, I meant "any application that uses for/in loops to iterate
> through objects that serve as collections".

Besides hasOwnProperty, for Arrays you could enumerate from 0 to
length-1. But perhaps you want non-indexed properties defined by users
on the instance to be enumerated (but again, not prototype user-defined
properties). That suggests using hasOwnProperty.

Ideally, there'd be a direct (no prototype enumeration) for..in variant,
but I kept the original language very simple, and no one has thought to
add such a construct in ECMA.

/be

Chris Zumbrunn

unread,
Mar 23, 2004, 8:56:07 PM3/23/04
to
Brendan Eich writes:

> I'm asking for a real-world example where such a loop breaks because of
> the user-defined prototype property. Almost all such loops that I've
> seen are inspecting/debugging loops, where the added prototype
> properties can be filtered out, by script or by the reader. It's not
> ideal, but it's not a fatal ("will break") situation.

OK, I see the proposed workarounds/solutions and I now realize why
you're asking for real-world examples.

It's true that the problem is limited to inspecting/debugging loops in
the cases of user-defined string methods or methods for other kinds of
objects that do not usually serve as collections. But everybody quickly
learns to avoid adding user-defined methods for the Object or Array
prototypes - because these objects are used as collections and are
regularly enumerated in for/in loops.

> An easy way for scripts to filter is to use Object.prototype.hasOwnProperty:

...


> Besides hasOwnProperty, for Arrays you could enumerate from 0 to
> length-1.

While this is an acceptable workaround for inspecting/debugging loops,
it can't be the solution for user-defined methods for Object and Array
because almost any existing Javascript code that has been written
expects for/in loops to enumerate these objects without the need for
such filtering. Adding a user-defined method for Object or Array would
break virtually any existing script.

Georg Maass writes:

> Do not prototype them to create your own variation. Derivate them to
> define your own variation.

I guess that would be the "correct" and "clean" solution. But I think
there are legitimate benefits (convenience, streamlined code structure)
that can be gained from adding user-defined methods to the standard
prototypes.

Brendan Eich writes:

> Ideally, there'd be a direct (no prototype enumeration) for..in variant,
> but I kept the original language very simple, and no one has thought to
> add such a construct in ECMA.

That wouldn't solve the problem because all the existing code that uses
the standard for/in statement would still break as soon as a
user-defined method is added to the Object or Array prototypes.

One real-world example that might serve well to illustrate what I mean
would be getter/setter methods for data conversion of Javascript objects
(for example to and from XML).

Chris

Brendan Eich

unread,
Mar 23, 2004, 11:04:07 PM3/23/04
to Chris Zumbrunn
Chris Zumbrunn wrote:

> One real-world example that might serve well to illustrate what I mean
> would be getter/setter methods for data conversion of Javascript objects
> (for example to and from XML).

If you mean someone calling Object.prototype.__defineGetter__('id', f),
or likewise for a setter, then the property that results in that case is
not enumerable in SpiderMonkey.

This looks to me like a bug introduced when the old getter= form was
deprecated and its code copied into new __defineGetter__ and
__defineSetter__ methods of Object.prototype, as the getter= code
includes JSPROP_ENUMERATE among the attributes. But, you can take
advantage of it for now.

The problem hinted at by my last posting is that it's hard to change JS
now, given all the implementations; harder still, as you point out, to
change it in incompatible ways. Your best bet is to lobby ECMA people,
if you can contact them, about getting Edition 4 changed.

Adding a way to define a non-enumerable property could be done in
SpiderMonkey -- is that something you could use well, or would you need
standard support to get other implementations to pay attention to the
change and implement the extension?

/be

Chris Zumbrunn

unread,
Mar 26, 2004, 8:21:57 PM3/26/04
to
Brendan Eich writes:

> Chris Zumbrunn wrote:
>
> > One real-world example that might serve well to illustrate what I mean
> > would be getter/setter methods for data conversion of Javascript objects
> > (for example to and from XML).
>
> If you mean someone calling Object.prototype.__defineGetter__('id', f),
> or likewise for a setter, then the property that results in that case is
> not enumerable in SpiderMonkey.
>
> This looks to me like a bug introduced when the old getter= form was
> deprecated and its code copied into new __defineGetter__ and
> __defineSetter__ methods of Object.prototype, as the getter= code
> includes JSPROP_ENUMERATE among the attributes. But, you can take
> advantage of it for now.

I didn't know about __defineSetter__ and __defineGetter__ at all. I've
had some trouble getting this to work in the environment where I use
Spidermonkey - but that's just our embedding that will need to be fixed.

> The problem hinted at by my last posting is that it's hard to change JS
> now, given all the implementations; harder still, as you point out, to
> change it in incompatible ways. Your best bet is to lobby ECMA people,
> if you can contact them, about getting Edition 4 changed.

Regarding ECMA4/JS2, I just found a list of changes Douglas Crockford
suggests at http://www.crockford.com/javascript/recommend.html
and "dontenum myClass.prototype.myMethod;" is on that list - I would
think he sent these suggestions to the ECMA people.

> Adding a way to define a non-enumerable property could be done in
> SpiderMonkey -- is that something you could use well, or would you need
> standard support to get other implementations to pay attention to the
> change and implement the extension?

No, I wouldn't need standard support. That's why I originally also asked
if somebody had already done or attempted a patch of this kind in their
implementations.

However, I would also need a way of doing this in Rhino. Does Rhino
provide anything similar to Spidermonkey's __defineSetter__ and
__defineGetter__?

Could a dontenum statement be added to both Spidermonkey and Rhino,
even-though it isn't part of the ECMA specs (yet)? That would be ideal!

Chris

0 new messages