for(i in array)

T

Thomas Mlynarczyk

Hi,

For objects (non-arrays) I can use for(i in object) to loop through all its
members. For arrays, this does not always seem to work, and I am forced to
use for(i=0; i<array.length;i++) instead. Is there a way to make an array
accessible using the for-in loop? During my experiments I found that if the
array is a member of an object, but not the first one, the for-in will
work... seems a strange behaviour to me, so I'd be grateful if someone could
shed some light on this for me.

Greetings,
Thomas
 
R

Richard Cornford

Thomas said:
For objects (non-arrays) I can use for(i in object)
to loop through all its members.

To loop through the _enumerable_ members.
For arrays, this does not always seem to work,

I have seen no evidence of any ECMAScript implementations exhibiting
incorrect (unspecified) behaviour with for-in loos (except Netscape 4,
with respect to the Type of the property name value, only).
and I am forced to use
for(i=0; i<array.length;i++) instead.

If the members of an Array object that have property names that
sufficiently resemble 32 bit unsigned integers are the subject of
interest (as is almost always the case) then a loop incrementing (or
decrementing) a number and limited by the Array's - length - property is
the correct/reliable approach.
Is there a way to make an array
accessible using the for-in loop?

Arrays are objects and will exhibit the (ECMA 262) specified behaviour
when used as the subject of a for-in loop.
During my experiments I found that if the array
is a member of an object, but not the first one, the for-in
will work... seems a strange behaviour to me, so I'd be
grateful if someone could shed some light on this for me.

In the above you have declared unshown code as 'working' or 'not
working', without stating the criteria for either. As, in a strictly
technical sense, all computer code 'works' (the computer mindlessly
follows the instructions provided regardless of the outcome), it is
almost always necessarily to explain what intended/expected behaviour
corresponds with your definition of 'works', and provide that
demonstrates how you are achieving 'not working'.

Richard.
 
T

Thomas Mlynarczyk

Also sprach Richard Cornford:
To loop through the _enumerable_ members.

Is there a website which explains this issue in more detail?
Arrays are objects and will exhibit the (ECMA 262) specified behaviour
when used as the subject of a for-in loop.

Does this mean if I access an array using for-in it should work and if it
doesn't there must be a bug in my script?
In the above you have declared unshown code as 'working' or 'not
working', without stating the criteria for either. As, in a strictly
technical sense, all computer code 'works' (the computer mindlessly
follows the instructions provided regardless of the outcome), it is
almost always necessarily to explain what intended/expected behaviour
corresponds with your definition of 'works', and provide that
demonstrates how you are achieving 'not working'.

Strangely, I was not able to reproduce the behaviour in a minimal test case,
so it seems that it is indeed a bug in my original script, even though I
cannot see how it could be possible. My script has a function which takes an
object as argument (usually created "on the fly" in the function call
statement). It loops through it using for-in and displays the member names
and their values. If a value is an object (or array), it recursively loops
through its members to display them as well.
 
M

Michael Winter

Thomas said:
Also sprach Richard Cornford:
[snip]
To loop through the _enumerable_ members.

Is there a website which explains this issue in more detail?

Not to my knowledge, though it is explained in the ECMAScript
specification[1] (8.6.1). In any case, it's quite simple.

All object properties have a set of attributes associated with them.
These attributes are ReadOnly, DontEnum, DontDelete, and Internal. The
specification gives standardised properties preset attributes -
namely, most (perhaps all? I'm not going to look right now :D) methods
and properties are marked DontEnum. Host objects may, or may not,
define attributes for their properties. It's up to the implementor.

Whilst you can access DontEnum properties, you can only do so
directly. The for..in statement will not discover these properties.

Unfortunately, user code cannot manipulate property attributes. Any
user-created properties will have no attributes set.
Does this mean if I access an array using for-in it should work and if it
doesn't there must be a bug in my script?

There might be a bug in the ECMAScript implementation, but yes, it
could be your code.

Hope that helps,
Mike

[1]
<URL:http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf>
 
R

Richard Cornford

Thomas said:
Also sprach Richard Cornford:

Is there a website which explains this issue in more detail?

What issue? ECMA 262 says that the for-in statement should behave in a
particular way and language implementations behave in that way.
Does this mean if I access an array using for-in it should
work and if it doesn't there must be a bug in my script?

How are you defining 'work' and 'doesn't (work)'?

^^^^^^^^^^^^
That should have read "provide code that ...".
Strangely, I was not able to reproduce the behaviour
in a minimal test case, so it seems that it is indeed
a bug in my original script, even though I cannot
see how it could be possible. ...
<snip>

And nobody else can _see_ it either.

However, when you cannot reproduce a problem by isolating the suspected
cause you have eliminated that possibility as the cause of the problem
and know that it is time to look elsewhere.

Richard.
 
T

Thomas Mlynarczyk

Also sprach Michael Winter:
All object properties have a set of attributes associated with them.
These attributes are ReadOnly, DontEnum, DontDelete, and Internal. The
specification gives standardised properties preset attributes -
namely, most (perhaps all? I'm not going to look right now :D) methods
and properties are marked DontEnum. Host objects may, or may not,
define attributes for their properties. It's up to the implementor.
Whilst you can access DontEnum properties, you can only do so
directly. The for..in statement will not discover these properties.
Unfortunately, user code cannot manipulate property attributes. Any
user-created properties will have no attributes set.

Thanks for the explanation. I had noticed, that, when looping recursively
through a DOM object (like document), the for-in loop seems to do several
rounds, but no data is retrieved. Moreover, in some browsers I get an error
like "Could not access...". Is this likely to be a bug in my script?
 
G

Grant Wagner

Thomas Mlynarczyk said:
Also sprach Michael Winter:


Thanks for the explanation. I had noticed, that, when looping
recursively
through a DOM object (like document), the for-in loop seems to do
several
rounds, but no data is retrieved. Moreover, in some browsers I get an
error
like "Could not access...". Is this likely to be a bug in my script?

No, it is not a bug in your script. Some properties of some host objects
in some browsers are not accessible.

For example, the following works as expected in Internet Explorer:

for (var prop in navigator)
{
document.write(
prop + ' = ' + navigator[prop] +
' (type: ' + typeof navigator[prop] + ')<br>'
);
}

However:

for (var prop in navigator.plugins)
{
document.write(
prop + ' = ' + navigator.plugins[prop] +
' (type: ' + typeof navigator.plugins[prop] + ')<br>'
);
}

Produces an "Object doesn't support this property or method" error, even
though navigator.plugins reports typeof "object" when enumerating the
navigator object.

As a result, it is not a good idea to recursively enumerate the
enumerable properties of host objects (and their child objects), since
you can not guarantee it will not produce an unrecoverable error.
 
T

Thomas Mlynarczyk

Also sprach Grant Wagner:
As a result, it is not a good idea to recursively enumerate the
enumerable properties of host objects (and their child objects), since
you can not guarantee it will not produce an unrecoverable error.

So there are objects which don't like to be asked about their properties...
And no way to find out before one tries accessing them? Or could I somehow
use try-catch to skip such objects?
 
D

Douglas Crockford

As a result, it is not a good idea to recursively enumerate the
So there are objects which don't like to be asked about their properties...
And no way to find out before one tries accessing them? Or could I somehow
use try-catch to skip such objects?

You can try, but that will produce syntax errors at load time on old
browsers.
 
D

Douglas Crockford

As a result, it is not a good idea to recursively enumerate the
You can try, but that will produce syntax errors at load time on old
browsers.

I have had some success with the isAlien function, but I haven't tested
it on all browsers.

function isAlien(a) {
return isObject(a) && typeof a.constructor != 'function';
}
 
T

Thomas Mlynarczyk

Also sprach Douglas Crockford:

Well, it doesn't have to work on NN<6, OP<7, IE<5 etc..
I have had some success with the isAlien function, but I haven't
tested it on all browsers.

function isAlien(a) {
return isObject(a) && typeof a.constructor != 'function';
}

So if(isAlien(myObject)) {/* don't use for-in on it */}? That, however,
seems to exclude all host objects, so I couldn't loop through the document
object.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top