myArray instanceof Array fails after passing to a different page

Discussion in 'Javascript' started by John MacIntyre, Sep 24, 2003.

  1. Hi,

    I have a page with a series of child pages loaded into an iframe. When I
    move from page to page, I store an object containing the child's control
    data in a variable on the main page, then use that data to populate the
    controls when the child page is opened again.

    One of these objects contains an Array, and the page reloads fine using
    myArray[0], myArray[1], etc... But when I try perform some array methods
    on it (i.e.slice) ... it does not recognize it as an array.

    By checking "myArray instanceof Array", I have determined that the object
    is seen as an array until it is passed to the parent page. Then "myArray
    instanceof Array" fails.

    Does anybody know why this is? And/Or how I can get around it?

    I managed to isolate the problem in the following HTML files.

    Thanks in advance,
    --
    John MacIntyre
    VC++ / VB / ASP / Database Developer
    http://www.johnmacintyre.ca



    -------------------------
    --- parent.htm ---
    -------------------------
    <HTML>
    <script>
    function getArray()
    {
    var ca;
    ca = ifra.getArray();
    alert(ca.join("-"));
    alert( "Parent : " + ((ca instanceof Array) ? "Type Array" :
    "Unknown
    Type"));
    }
    </script>
    <BODY>
    <button onclick="getArray()">Check child array type</button><br>
    <IFRAME id=ifra name=ifra src="C1.htm"></IFRAME>
    </BODY>
    </HTML>



    -------------------------
    --- C1.htm ---
    -------------------------
    <script>
    function getArray()
    {
    var a = new Array( 1,2,3,5,8,13,21,34,55,89);
    return a;
    }

    function btn_onclick()
    {
    var a = getArray();
    alert( "Child : " + ((a instanceof Array) ? "Type Array" :
    "Unknown
    Type"));
    }
    </script>
    <BODY>
    <button onclick="btn_onclick();">Click for Array</button>
    </BODY>
    </HTML>
     
    John MacIntyre, Sep 24, 2003
    #1
    1. Advertising

  2. > I have a page with a series of child pages loaded into an iframe. When I
    > move from page to page, I store an object containing the child's control
    > data in a variable on the main page, then use that data to populate the
    > controls when the child page is opened again.
    >
    > One of these objects contains an Array, and the page reloads fine using
    > myArray[0], myArray[1], etc... But when I try perform some array methods
    > on it (i.e.slice) ... it does not recognize it as an array.
    >
    > By checking "myArray instanceof Array", I have determined that the object
    > is seen as an array until it is passed to the parent page. Then "myArray
    > instanceof Array" fails.
    >
    > Does anybody know why this is? And/Or how I can get around it?


    When you say 'Array', you are talking about 'window.Array'. 'window' is the
    browser's context object, and you get one per page (or frame). All of the arrays
    created within a context will have their constructor property set to
    'window.Array'.

    An array created in a different context has a different window.Array, so your
    test

    myArray instanceof Array

    fails. The ECMAScript standard does not discuss multiple contexts, even though
    virtually all implementations support them. The ECMAScript standard also fails
    to provide a reliable technique for testing the type of arrays. The obvious
    thing would have been

    typeof myArray == 'array'

    except that unfortunately, it turns out that

    typeof myArray == 'object'

    which not very useful.

    You might try testing for the presence of a well-know array method.

    typeof myArray.sort == 'function'

    This is not infallible, but it is better than the useless instanceof operator.

    www.crockford.com/javascript/javascript.html
     
    Douglas Crockford, Sep 24, 2003
    #2
    1. Advertising

  3. John MacIntyre

    Dom Leonard Guest

    John MacIntyre wrote:
    > Hi,
    >
    > I have a page with a series of child pages loaded into an iframe. When I
    > move from page to page, I store an object containing the child's control
    > data in a variable on the main page, then use that data to populate the
    > controls when the child page is opened again.


    > One of these objects contains an Array, and the page reloads fine using
    > myArray[0], myArray[1], etc... But when I try perform some array methods
    > on it (i.e.slice) ... it does not recognize it as an array.



    You will be familiar with the fact that page javascript values are
    destroyed by closing a window, page reload, document.write after
    window.onload or simply navigating to a new page.

    Less well known, but corroborated by testing, is that the *value* of at
    least some of the global properties supplied by the scripting engine are
    also updated as a result of navigation within a window. In particular,
    the value of window.Array seen within the iframe is not constant across
    page navigation.

    What your program does is to execute code defined within the iframe from
    a thread originating in the parent. For IE at least, the empirical
    result is that the Array object returned is created in object data space
    of the parent and is not destroyed by changing URLs within the iframe.

    However, array methods are inherited from Array.prototype, and the array
    returned from iframe code is prototyped on
    <iframe>.window.Array.prototype. This object *is* being destroyed by
    navigation within the iframe.

    In effect the array stored in the parent has lost its prototype object
    [1]. Local properties of the array can still be accessed as you have
    already found.

    The suggested workaround is to copy non-object values from the iframe to
    an array created by parent frame code, in a parent frame execution
    thread. (Or "experiment, experiment, experiment!" :)

    <snip>

    > function getArray()
    > {
    > var ca;
    > ca = ifra.getArray();
    > alert(ca.join("-"));
    > alert( "Parent : " + ((ca instanceof Array) ? "Type Array" : "Unknown Type"));
    > }


    [1] "myObject instanceof myConstructor" answers the question "is the
    current value of myConstructor.prototype in the prototype chain of
    myObject". If you executed

    function showType()
    {
    alert("ca instanceof ifra.window.Array: "
    + (ca instanceof ifra.window.Array));
    }
    you would see true immediately after calling getArray(), but false if
    the iframe document is replaced in the mean time.

    BTW, this response is not intended to replace Douglas Crawford's
    execellent reply, but simply to investigate different aspects and look
    at some snipped code.

    HTH,

    Dom
     
    Dom Leonard, Sep 24, 2003
    #3
  4. John MacIntyre

    Dom Leonard Guest

    Dom Leonard wrote:

    > BTW, this response is not intended to replace Douglas

    Crockford's
    > execellent reply,


    Sorry Douglas, I primarily file by first name in my head and didn't spot
    misquoting your last name until after posting. My sincere appologies.

    Dom
     
    Dom Leonard, Sep 24, 2003
    #4
  5. Thanks, guys for the great replies. These were among the best explanations
    I've ever gotten from a newsgroup.

    For the record, the way I got around this is to create a function in the
    parent page which I called from the child page. This way when it was passed
    back to the parent ... it was recognized. Not the cleanest way .. but it
    was effective.

    Thanks again,
    --
    John MacIntyre
    VC++ / VB / ASP / Database Developer
    http://www.johnmacintyre.ca


    "Dom Leonard" <> wrote in message
    news:Lvccb.182$...
    > Dom Leonard wrote:
    >
    > > BTW, this response is not intended to replace Douglas

    > Crockford's
    > > execellent reply,

    >
    > Sorry Douglas, I primarily file by first name in my head and didn't spot
    > misquoting your last name until after posting. My sincere appologies.
    >
    > Dom
    >
    >
    >
    >
    >
     
    John MacIntyre, Sep 24, 2003
    #5
    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. Mike B
    Replies:
    2
    Views:
    296
    Rapscallion
    Jun 8, 2005
  2. Replies:
    21
    Views:
    22,215
  3. Duim
    Replies:
    2
    Views:
    305
  4. Fabian
    Replies:
    13
    Views:
    235
    Lasse Reichstein Nielsen
    Nov 18, 2003
  5. Andrew Phillipo
    Replies:
    3
    Views:
    140
    Martin Honnen
    Sep 22, 2005
Loading...

Share This Page