Its the isArray() function thing again

Discussion in 'Javascript' started by Aaron Gray, Jul 26, 2008.

  1. Aaron Gray

    Aaron Gray Guest

    I know this has probably been argued to death, but I am going to raise it
    fresh again, and basically lets have an unofficial 'isArray()' contest that
    we can hopefully put it to rest as best as we can.

    I have found things that work perfectly well as long as you don't try them
    on MSIE, ie adding Object and Array prototype isArray functions, thus :-

    Object.prototype.isArray = function() { return false }
    Array.prototype.isArray = function() { return true }

    This falls down on builtin browser types in IE, so is no good.

    The one version that I have seen is :-

    function isArray( a) { return typeof a.push == "function" }

    Prototype for all its "failings" extends object and provides :-

    Object.extend(Object, {
    isArray: function(object) {
    return object != null && typeof object == "object" &&
    'splice' in object && 'join' in object;
    }
    });

    So checking of non null and splice and join maybe better than just checking
    for push.

    So something like :-

    function isArray( o) { return o != null && typeof o == "object" &&
    'push' in o }

    But I am not sure when 'in' was actually introduced.

    function isArray( o) { return o != null && typeof o == "object" &&
    typeof o.push == "function" }

    Would probably do best/better. This is what I have settled on for now.

    Then there was the advice to use === rather than ==, but I dont know when
    that was introduced too, or whether it is really necessary as == works just
    as well AFAICS.

    Any critisisms, advances, or advice ?

    Aaron
     
    Aaron Gray, Jul 26, 2008
    #1
    1. Advertising

  2. Gregor Kofler, Jul 26, 2008
    #2
    1. Advertising

  3. On Jul 26, 3:03 pm, "Aaron Gray" <> wrote:
    > I know this has probably been argued to death, but I am going to raise it
    > fresh again, and basically lets have an unofficial 'isArray()' contest that
    > we can hopefully put it to rest as best as we can.


    In your actual application code, why are you ever having any trouble
    knowing if a variable references an Array or not? If a function's API
    states it should recieve an array argument, then just send it an array
    argument. If it states it should receive a number, don't send it an
    array. Be careful about bringing the baggage of focusing on type
    checking and casting from languages like Java or C++ to your
    JavaScript programming.

    > I have found things that work perfectly well as long as you don't try them
    > on MSIE, ie adding Object and Array prototype isArray functions, thus :-
    >
    > Object.prototype.isArray = function() { return false }
    > Array.prototype.isArray = function() { return true }


    Augmenting built in prototypes with generic names like "isArray" is
    likely to collide in an envronment where multiple authors are writing
    the JavaScript.

    http://peter.michaux.ca/article/7979


    > This falls down on builtin browser types in IE, so is no good.
    >
    > The one version that I have seen is :-
    >
    > function isArray( a) { return typeof a.push == "function" }


    That is a very wimpy test in general.


    > Prototype for all its "failings" extends object and provides :-


    The quotation marks are not necessary.


    > Object.extend(Object, {
    > isArray: function(object) {
    > return object != null && typeof object == "object" &&
    > 'splice' in object && 'join' in object;
    > }
    > });


    Why they think writing

    Object.isArray

    is any different than

    PrototypeJS.isArray

    I will never understand.


    > So checking of non null and splice and join maybe better than just checking
    > for push.
    >
    > So something like :-
    >
    > function isArray( o) { return o != null && typeof o == "object" &&
    > 'push' in o }
    >
    > But I am not sure when 'in' was actually introduced.
    >
    > function isArray( o) { return o != null && typeof o == "object" &&
    > typeof o.push == "function" }


    So if I define a new object in JavaScript with a push function it will
    pass your test. That is a very weak test.


    > Would probably do best/better. This is what I have settled on for now.
    >
    > Then there was the advice to use === rather than ==, but I dont know when
    > that was introduced too,


    http://pointedears.de/scripts/es-matrix/


    > or whether it is really necessary as == works just
    > as well AFAICS.


    They are not the same. == and != do type coercion.

    http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Comparison_Operators


    > Any critisisms, advances, or advice ?


    What's wrong with

    if (obj instanceof Array) {
    // do stuff
    }

    http://developer.mozilla.org/en/doc...erators:Special_Operators:instanceof_Operator

    Peter
     
    Peter Michaux, Jul 26, 2008
    #3
  4. "Aaron Gray" <> writes:

    > I know this has probably been argued to death, but I am going to raise it
    > fresh again, and basically lets have an unofficial 'isArray()' contest that
    > we can hopefully put it to rest as best as we can.


    Is there a setting where

    obj instanceof Array

    fails to detect an Array?

    ....
    > Prototype for all its "failings" extends object


    That's one failing right there :)
    I thought they stopped doing that in later versions?

    > and provides :-
    >
    > Object.extend(Object, {
    > isArray: function(object) {
    > return object != null && typeof object == "object" &&
    > 'splice' in object && 'join' in object;


    Sigh. Feature detection is good for detecting features. This is detection
    by inference. This is as bad as
    var isIE = document.all ? 1 : 0;
    (ok, slightly better, the isIE example has more bad points than it has
    keywords)

    > So checking of non null and splice and join maybe better than just checking
    > for push.


    "maybe" is the operative word. I.e., it's shooting blind and hoping to
    be lucky.

    > So something like :-
    >
    > function isArray( o) { return o != null && typeof o == "object" &&
    > 'push' in o }
    >
    > But I am not sure when 'in' was actually introduced.


    JScript 5.6
    JavaScript 1.4

    Same versions as "instanceof", btw.

    > function isArray( o) { return o != null && typeof o == "object" &&
    > typeof o.push == "function" }
    >
    > Would probably do best/better. This is what I have settled on for now.


    And when we implement a stack:

    function Stack() {}
    Stack.prototype.push = function(o) {
    this.head = {elem: o, next: this.head }
    };
    Stack.prototype.pop = function() {
    var head = this.head;
    if (head) {
    var elem = head.elem;
    this.head = head.next;
    return elem;
    }
    };

    it suddently qualifies as an array?

    An object is an Array if it inherits Array.prototype. That's the
    prototype based definition of inheritance.

    > Then there was the advice to use === rather than ==, but I dont know when
    > that was introduced too, or whether it is really necessary as == works just
    > as well AFAICS.


    It's the same when dealing with objects. The "==" operator performs
    type conversion in some cases, whereas the "===" requires both
    operands to have the same type. When the operands are objects, they
    work exactly the same,

    > Any critisisms, advances, or advice ?


    What problem are you trying to solve?
    Why?


    In any case, don't try to be clever. Either use "instanceof", or, if
    it's *really* necessary to support ancient browsers, test simple
    things:

    function isArray(o) {
    return o && o.constructor == Array;
    }

    It's easy to cheat, but anybody actively trying to cheat is going to
    succeede anyway.

    /L
    --
    Lasse Reichstein Nielsen
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Jul 26, 2008
    #4
  5. Aaron Gray meinte:
    > I know this has probably been argued to death, but I am going to raise it
    > fresh again, and basically lets have an unofficial 'isArray()' contest that
    > we can hopefully put it to rest as best as we can.


    Crockford suggests

    var is_array = function(v) {
    return v && typeof v === "object" && v.constructor === Array;
    }

    (wont work on arrays in other windows/frames)

    or

    var is_array = function(v) {
    return v && typeof v === "object" && typeof v.length === "number" &&
    typeof v.splice === "function" && !(v.propertyIsEnumerable("length"));
    }

    (I suppose he took splice() because it's a relatively "rare" method)

    Gregor


    --
    http://photo.gregorkofler.at ::: Landschafts- und Reisefotografie
    http://web.gregorkofler.com ::: meine JS-Spielwiese
    http://www.image2d.com ::: Bildagentur für den alpinen Raum
     
    Gregor Kofler, Jul 26, 2008
    #5
  6. Aaron Gray

    Aaron Gray Guest

    "Lasse Reichstein Nielsen" <> wrote in message
    news:...
    > "Aaron Gray" <> writes:
    >
    >> I know this has probably been argued to death, but I am going to raise it
    >> fresh again, and basically lets have an unofficial 'isArray()' contest
    >> that
    >> we can hopefully put it to rest as best as we can.

    >
    > Is there a setting where
    >
    > obj instanceof Array
    >
    > fails to detect an Array?


    Don't know. But I had forgotten about 'instanceof Array' and thats exactly
    what I need for this specific problem.

    I think people use the other 'weaker' methods to allow inclusion of array
    like objects as well as Arrays.

    > In any case, don't try to be clever. Either use "instanceof", or, if
    > it's *really* necessary to support ancient browsers, test simple
    > things:
    >
    > function isArray(o) {
    > return o && o.constructor == Array;
    > }


    Thomas is right, I really should read ECMA-262 properly.

    Many thanks,

    Aaron
     
    Aaron Gray, Jul 27, 2008
    #6
  7. Aaron Gray

    dhtml Guest

    On Jul 26, 3:36 pm, Lasse Reichstein Nielsen <> wrote:
    > "Aaron Gray" <> writes:
    > > I know this has probably been argued to death, but I am going to raise it
    > > fresh again, and basically lets have an unofficial 'isArray()' contest that
    > > we can hopefully put it to rest as best as we can.

    >
    > Is there a setting where
    >
    >   obj instanceof Array
    >
    > fails to detect an Array?


    There is: When obj is an Array in a different frame than the Array
    constructor, it would be constructed via a different Array
    constructor, and so obj instanceof Array would have to be false.
    otherFrame.obj instanceof otherFrame.Array would be true, though.


    > > Prototype for all its "failings" extends object


    That was quite a long time ago.

    > That's one failing right there :)
    > I thought they stopped doing that in later versions?


    Yes, they did.

    Garrett


    > /L
     
    dhtml, Jul 27, 2008
    #7
  8. On Jul 26, 4:52 pm, dhtml <> wrote:

    > > "Aaron Gray" <> writes:


    > > > Prototype for all its "failings" extends object

    >
    > That was quite a long time ago.


    They are still extending "Object" unnecessarily with function-valued
    properties that could be added to any object. Adding them to "Object"
    is just confusing, in my opinion. They also choose very generic names
    in shared namespaces which is another problem of theirs.

    http://www.prototypejs.org/api/object

    Peter
     
    Peter Michaux, Jul 27, 2008
    #8
  9. Aaron Gray

    RobG Guest

    On Jul 27, 9:52 am, dhtml <> wrote:
    > On Jul 26, 3:36 pm, Lasse Reichstein Nielsen <> wrote:
    >
    > > "Aaron Gray" <> writes:
    > > > I know this has probably been argued to death, but I am going to raise it
    > > > fresh again, and basically lets have an unofficial 'isArray()' contest that
    > > > we can hopefully put it to rest as best as we can.

    >
    > > Is there a setting where

    >
    > >   obj instanceof Array

    >
    > > fails to detect an Array?

    >
    > There is: When obj is an Array in a different frame than the Array
    > constructor, it would be constructed via a different Array
    > constructor, and so obj instanceof Array would have to be false.
    > otherFrame.obj instanceof otherFrame.Array would be true, though.
    >
    > > > Prototype for all its "failings" extends object

    >
    > That was quite a long time ago.
    >
    > > That's one failing right there :)
    > > I thought they stopped doing that in later versions?

    >
    > Yes, they did.


    They stopped extending Object.prototype.

    --
    Rob
     
    RobG, Jul 27, 2008
    #9
  10. Aaron Gray

    dhtml Guest

    On Jul 26, 7:10 pm, RobG <> wrote:
    > On Jul 27, 9:52 am, dhtml <> wrote:
    >
    >
    >
    > > On Jul 26, 3:36 pm, Lasse Reichstein Nielsen <> wrote:

    >
    > > > "Aaron Gray" <> writes:
    > > > > I know this has probably been argued to death, but I am going to raise it
    > > > > fresh again, and basically lets have an unofficial 'isArray()' contest that
    > > > > we can hopefully put it to rest as best as we can.

    >
    > > > Is there a setting where

    >
    > > >   obj instanceof Array

    >
    > > > fails to detect an Array?

    >
    > > There is: When obj is an Array in a different frame than the Array
    > > constructor, it would be constructed via a different Array
    > > constructor, and so obj instanceof Array would have to be false.
    > > otherFrame.obj instanceof otherFrame.Array would be true, though.

    >
    > > > > Prototype for all its "failings" extends object

    >
    > > That was quite a long time ago.

    >
    > > > That's one failing right there :)
    > > > I thought they stopped doing that in later versions?

    >
    > > Yes, they did.

    >
    > They stopped extending Object.prototype.
    >


    Ah, right that's what I was thinking about. Modifying
    Object.prototype. That was very bad.

    They still extend Object, which is not as bad. They add a clone()
    method to Object, and clone is an ES3.1 Proposal. I asked Allen about
    that

    Object.clone is proposed for ES 3.1. I did mention it on the list, but
    Allen was replying to a lot of responders, so he probably missed what
    I wrote:

    | It seems like Object.clone might create compatibility with existing
    | code. There is already a widespread use of an Object.clone on the
    web.


    Garrett

    > --
    > Rob
     
    dhtml, Jul 27, 2008
    #10
  11. "dhtml" wrote:

    [snip]

    > > > > "Aaron Gray" wrote:


    [snip]

    > > > > > Prototype for all its "failings" extends object


    [snip]

    > They still extend Object, which is not as bad. They add a clone()
    > method to Object, and clone is an ES3.1 Proposal. I asked Allen about
    > that
    >
    > Object.clone is proposed for ES 3.1. I did mention it on the list, but
    > Allen was replying to a lot of responders, so he probably missed what


    Who is "Allen"?

    > I wrote:
    >
    > | It seems like Object.clone might create compatibility with existing
    > | code. There is already a widespread use of an Object.clone on the
    > web.


    "compatibility" or "incompatibility" with Prototype.js' Object.clone?
    It looks to me like there will be incompatibility as Prototype.js'
    Object.clone is a shallow copy and the ES3.1 Object.clone is a much
    deeper clone of an Object. This is why adding generically named
    properties in shared namespaces is a problem. The Prototype.js
    developers have been burned by this at least a few times in the past
    two years. That may imply they have influence over the evolution of
    JavaScript and the DOM. Unfortunately it also means they are causing
    unnecessary maintenance headaches for Prototype.js users.

    Peter
     
    Peter Michaux, Jul 27, 2008
    #11
  12. Aaron Gray

    Jorge Guest

    On Jul 27, 5:55 pm, Peter Michaux <> wrote:
    >
    > > Object.clone is proposed for ES 3.1. I did mention it on the list, but
    > > Allen was replying to a lot of responders, so he probably missed what
    > > I wrote.

    >
    > Who is "Allen"?
    >


    Allen Wirfs-Brock, http://preview.tinyurl.com/5hf4na

    --Jorge.
     
    Jorge, Jul 27, 2008
    #12
  13. Aaron Gray

    Jorge Guest

    Jorge, Jul 27, 2008
    #13
  14. Jorge wrote:
    On Jul 27, 5:55 pm, Peter Michaux wrote:
    >
    > > Object.clone is proposed for ES 3.1. I did mention it on the list,
    > > but
    > > Allen was replying to a lot of responders, so he probably missed
    > > what
    > > I wrote.

    >
    > Who is "Allen"?
    >


    Allen Wirfs-Brock, http://preview.tinyurl.com/5hf4na

    There is little point in posting tinyurl URLs as nobody in their right
    mind would follow one, just as nobody in their right mind would follow a
    URL found in a spam post.

    Richard.
     
    Richard Cornford, Jul 27, 2008
    #14
  15. Aaron Gray

    Jorge Guest

    On Jul 27, 11:53 pm, "Richard Cornford" <>
    wrote:
    >
    > Allen Wirfs-Brock,http://preview.tinyurl.com/5hf4na
    >
    > There is little point in posting tinyurl URLs as nobody in their right
    > mind would follow one, just as nobody in their right mind would follow a
    > URL found in a spam post.
    >


    Not even if it points to a preview, like that one ?
    We Mac users aren't so frightened of urls.

    --Jorge.
     
    Jorge, Jul 27, 2008
    #15
  16. dhtml wrote:
    <snip>
    > Object.clone is proposed for ES 3.1. I did mention it on the
    > list, but Allen was replying to a lot of responders, so he
    > probably missed what I wrote:
    >
    >| It seems like Object.clone might create compatibility with
    >| existing code. There is already a widespread use of an
    >| Object.clone on the web.


    Assuming you mean "incompatibility" where you wrote "compatibility",
    then ES 3.1 defining an - Object.clone - method is not an issue unless
    it is defined as a read-only (or ES 3.1's equivalent of read-only). If a
    script loads in into (and is executed in) an ES 3.1 environment and that
    script assignees its own method to - Obejct.clone - then so long as that
    assignment succeeds code in the same context that uses - Object.clone -
    will be using the version it is expecting to use.

    Richard.
     
    Richard Cornford, Jul 27, 2008
    #16
  17. Jorge wrote:
    > On Jul 27, 11:53 pm, Richard Cornford wrote:
    >>> Allen Wirfs-Brock,http://preview.tinyurl.com/5hf4na

    >>
    >> There is little point in posting tinyurl URLs as nobody
    >> in their right mind would follow one, just as nobody in
    >> their right mind would follow a URL found in a spam post.

    >
    > Not even if it points to a preview, like that one ?


    How would it be possible to determine what it points to without
    following it?

    > We Mac users aren't so frightened of urls.


    It is probably best if I don't comment on that.

    Richard.
     
    Richard Cornford, Jul 27, 2008
    #17
  18. Aaron Gray

    Jorge Guest

    On Jul 28, 12:26 am, "Richard Cornford" <>
    wrote:
    >
    > It is probably best if I don't comment on that.
    >


    Thanks. I also know about *that* contest.

    --Jorge.
     
    Jorge, Jul 27, 2008
    #18
  19. Aaron Gray

    dhtml Guest

    On Jul 27, 3:22 pm, "Richard Cornford" <>
    wrote:
    > dhtml wrote:



    >
    > >|  It seems like Object.clone might create compatibility with
    > >|  existing code. There is already a widespread use of an
    > >|  Object.clone on the web.

    >
    > Assuming you mean "incompatibility" where you wrote "compatibility",


    I remember thinking "compatibility issue" when I was typing.

    > then ES 3.1 defining an - Object.clone - method is not an issue unless
    > it is defined as a read-only (or ES 3.1's equivalent of read-only). If a
    > script loads in into (and is executed in) an ES 3.1 environment and that
    > script assignees its own method to - Obejct.clone - then so long as that
    > assignment succeeds code in the same context that uses - Object.clone -
    > will be using the version it is expecting to use.
    >


    Where "it" is the PrototypeJS library itself.

    A user of PrototypeJS would have to contend with things like:

    <script>
    Object.clone( o };
    </script>

    <script src="prototype-1.7.js"></script>

    <script>
    Object.clone( o };
    </script>

    PrototypeJS.cloneObject would be safer.

    Garrett

    > Richard.
     
    dhtml, Jul 28, 2008
    #19
    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. Laphan
    Replies:
    11
    Views:
    318
    StephenMcC
    Nov 22, 2004
  2. thunk
    Replies:
    1
    Views:
    318
    thunk
    Mar 30, 2010
  3. thunk
    Replies:
    0
    Views:
    491
    thunk
    Apr 1, 2010
  4. thunk
    Replies:
    14
    Views:
    629
    thunk
    Apr 3, 2010
  5. Matt Kruse

    Robust isArray() ?

    Matt Kruse, Dec 14, 2006, in forum: Javascript
    Replies:
    33
    Views:
    591
    Richard Cornford
    Dec 22, 2006
Loading...

Share This Page