for(i in array)

Discussion in 'Javascript' started by Thomas Mlynarczyk, Feb 26, 2005.

  1. 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
    Thomas Mlynarczyk, Feb 26, 2005
    #1
    1. Advertising

  2. Thomas Mlynarczyk wrote:
    > 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.
    Richard Cornford, Feb 26, 2005
    #2
    1. Advertising

  3. Also sprach Richard Cornford:

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

    >
    > 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.
    Thomas Mlynarczyk, Feb 27, 2005
    #3
  4. Thomas Mlynarczyk wrote:

    > 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.

    >> 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?


    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>

    --
    Michael Winter
    Replace ".invalid" with ".uk" to reply by e-mail.
    Michael Winter, Feb 27, 2005
    #4
  5. Thomas Mlynarczyk wrote:
    > Also sprach Richard Cornford:
    >> Thomas Mlynarczyk wrote:
    >>> For objects (non-arrays) I can use for(i in object)
    >>> to loop through all its members.

    >>
    >> To loop through the _enumerable_ members.

    >
    > 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.

    >> 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?


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

    <snip>
    >> ..., it is almost always necessarily to explain
    >> what intended/expected behaviour corresponds
    >> with your definition of 'works', and provide that

    ^^^^^^^^^^^^
    That should have read "provide code 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. ...

    <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.
    Richard Cornford, Feb 27, 2005
    #5
  6. 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?
    Thomas Mlynarczyk, Mar 1, 2005
    #6
  7. Thomas Mlynarczyk

    Grant Wagner Guest

    "Thomas Mlynarczyk" <> wrote in message
    news:d01cbl$qso$04$-online.com...
    > 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?


    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.

    --
    Grant Wagner <>
    comp.lang.javascript FAQ - http://jibbering.com/faq
    Grant Wagner, Mar 1, 2005
    #7
  8. 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?
    Thomas Mlynarczyk, Mar 1, 2005
    #8
  9. >>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?


    You can try, but that will produce syntax errors at load time on old
    browsers.
    Douglas Crockford, Mar 2, 2005
    #9
  10. >>> 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?

    >
    >
    > 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';
    }
    Douglas Crockford, Mar 2, 2005
    #10
  11. Also sprach Douglas Crockford:

    >>> use try-catch to skip such objects?

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


    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.
    Thomas Mlynarczyk, Mar 2, 2005
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Daniel
    Replies:
    1
    Views:
    1,030
    Kevin Collins
    Aug 14, 2003
  2. S300
    Replies:
    4
    Views:
    21,950
    Roedy Green
    Aug 19, 2003
  3. Mara Guida

    const and array of array (of array ...)

    Mara Guida, Sep 2, 2009, in forum: C Programming
    Replies:
    3
    Views:
    465
    David RF
    Sep 3, 2009
  4. Tom
    Replies:
    3
    Views:
    187
    salsablr
    Dec 20, 2004
  5. Tuan  Bui
    Replies:
    14
    Views:
    452
    it_says_BALLS_on_your forehead
    Jul 29, 2005
Loading...

Share This Page