Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   Robust isArray() ? (http://www.velocityreviews.com/forums/t928723-robust-isarray.html)

Matt Kruse 12-14-2006 05:03 PM

Robust isArray() ?
 
I'm seeking the most robust and backwards-compatible (ie, no instanceof)
isArray function.

Here's what I have:

function defined(o) {
return typeof(o)!="undefined";
}
function isArray(o) {
// If these conditions aren't met, it certainly isn't an Array
if (o==null || typeof(o)!="object" || typeof(o.length)!="number") {
return false;
}
// Check to see if the object is an instance of the window's Array object
if (defined(Array) && defined(o.constructor) && o.constructor==Array) {
return true;
}
// It might be an array defined from another window object - check to see
if it has an Array's methods
if (typeof(o.join)=="function" && typeof(o.sort)=="function" &&
typeof(o.reverse)=="function") {
return true;
}
// As a last resort, let's see if index [0] is defined
return (o.length==0 || defined(o[0]));
};

Suggestions?

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com



Julian Turner 12-14-2006 06:38 PM

Re: Robust isArray() ?
 

Matt Kruse wrote:

[snip]
> // It might be an array defined from another window object - check to see
> if it has an Array's methods
> if (typeof(o.join)=="function" && typeof(o.sort)=="function" &&
> typeof(o.reverse)=="function") {
> return true;
> }

[/snip]

Could you could do a toString instead on the constructor, and check
that?

> // As a last resort, let's see if index [0] is defined
> return (o.length==0 || defined(o[0]));
> };


Would that catch NodeLists and HTMLCollections?

I.e. are you looking for objects that are genuine JavaScript "Arrays"
or objects which have a certain minimum interface, like "length" and
"[]" index access.

I note also that "arguments" in IE has "Object" as its constructor, but
"Array" in Opera or Firefox I think.

Regards


Matt Kruse 12-14-2006 08:41 PM

Re: Robust isArray() ?
 
Julian Turner wrote:
> Could you could do a toString instead on the constructor, and check
> that?


I don't think so, because that can vary between browsers and doesn't return
just a single string like "Array".

>> // As a last resort, let's see if index [0] is defined
>> return (o.length==0 || defined(o[0]));
>> };

> Would that catch NodeLists and HTMLCollections?


Yup.

> I.e. are you looking for objects that are genuine JavaScript "Arrays"
> or objects which have a certain minimum interface, like "length" and
> "[]" index access.


The latter. Something that must (or can) be iterated over, rather than
interacted with directly.

> I note also that "arguments" in IE has "Object" as its constructor,
> but "Array" in Opera or Firefox I think.


The provided functions works in both cases.

I guess one thing I'm also looking for is something that is most certainly
NOT an array, but returns true with the provided function. Then, depending
on if the test case is practical or not, I can re-think it. I don't think a
perfect solution exists.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com



Dr J R Stockton 12-14-2006 11:30 PM

Re: Robust isArray() ?
 
In comp.lang.javascript message <els04h030rh@news4.newsguy.com>, Thu, 14
Dec 2006 11:03:11, Matt Kruse <newsgroups@mattkruse.com> wrote:
> ...
> // As a last resort, let's see if index [0] is defined
> return (o.length==0 || defined(o[0]));


If something with contents matching those of o = [,1] can get that
far, the code will return false in IE6.

But, on the principle of Feature Detection, rather than trying to see
what it "*is*", should one not be testing whether it will *do* what one
wants it to do? If there is, for example, no intention of using its
(possible) .Sort method, then there should be no need to test for .sort
- unless one believes in the Shibboleth Method.
--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk DOS 3.3, 6.20; WinXP.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links.
PAS EXE TXT ZIP via <URL:http://www.merlyn.demon.co.uk/programs/00index.htm>
My DOS <URL:http://www.merlyn.demon.co.uk/batfiles.htm> - also batprogs.htm.

Douglas Crockford 12-15-2006 12:13 AM

Re: Robust isArray() ?
 
Matt Kruse wrote:
> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
> isArray function.


How backwards do you have to go? JavaScript 1.0 didn't have arrays at all.

function isArray(v) {
return v && typeof v === 'object' && typeof v.length === 'number' &&
!(v.propertyIsEnumerable('length'));
}

It thinks that the arguments object is an array (which it ought to be (but isn't)).

http://javascript.crockford.com/

Matt Kruse 12-15-2006 03:20 AM

Re: Robust isArray() ?
 
Dr J R Stockton wrote:
>> // As a last resort, let's see if index [0] is defined
>> return (o.length==0 || defined(o[0]));

> If something with contents matching those of o = [,1] can get that
> far...


It wouldn't.

> But, on the principle of Feature Detection, rather than trying to see
> what it "*is*", should one not be testing whether it will *do* what
> one wants it to do? If there is, for example, no intention of using
> its (possible) .Sort method, then there should be no need to test for
> .sort - unless one believes in the Shibboleth Method.


Please do tell how you would "feature detect" whether an object can be
enumerated over using numeric indexes?

I don't see any fool-proof way to do it, thereby requiring a more complex
isArray function and inferring features rather than detecting them.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com



Matt Kruse 12-15-2006 03:28 AM

Re: Robust isArray() ?
 
Douglas Crockford wrote:
> How backwards do you have to go? JavaScript 1.0 didn't have arrays at
> all.


Then it would be hard to detect them ;)

> function isArray(v) {
> return v && typeof v === 'object' && typeof v.length === 'number'
> && !(v.propertyIsEnumerable('length'));
> }


How compatible is propertyIsEnumerable?

> It thinks that the arguments object is an array (which it ought to be
> (but isn't)).


It behaves like one, so IMO it should return true.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com



Randy Webb 12-15-2006 04:05 AM

Re: Robust isArray() ?
 
Matt Kruse said the following on 12/14/2006 12:03 PM:
> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
> isArray function.
>
> Here's what I have:
>
> function defined(o) {
> return typeof(o)!="undefined";
> }
> function isArray(o) {
> // If these conditions aren't met, it certainly isn't an Array
> if (o==null || typeof(o)!="object" || typeof(o.length)!="number") {
> return false;
> }
> // Check to see if the object is an instance of the window's Array object
> if (defined(Array) && defined(o.constructor) && o.constructor==Array) {
> return true;
> }
> // It might be an array defined from another window object - check to see
> if it has an Array's methods
> if (typeof(o.join)=="function" && typeof(o.sort)=="function" &&
> typeof(o.reverse)=="function") {
> return true;
> }
> // As a last resort, let's see if index [0] is defined
> return (o.length==0 || defined(o[0]));
> };
>
> Suggestions?


var myArray = new Array();
myArray[0] = "Its an array";
myArray[1] = "It really is an array!";
alert(isArray('myArray'))

IE7: false
Opera 9: false
Firefox 2.0: false

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

Randy Webb 12-15-2006 07:02 AM

Re: Robust isArray() ?
 
Randy Webb said the following on 12/14/2006 11:05 PM:
> Matt Kruse said the following on 12/14/2006 12:03 PM:
>> I'm seeking the most robust and backwards-compatible (ie, no
>> instanceof) isArray function.
>>
>> Here's what I have:
>>
>> function defined(o) {
>> return typeof(o)!="undefined";
>> }
>> function isArray(o) {
>> // If these conditions aren't met, it certainly isn't an Array
>> if (o==null || typeof(o)!="object" || typeof(o.length)!="number") {
>> return false;
>> }
>> // Check to see if the object is an instance of the window's Array
>> object
>> if (defined(Array) && defined(o.constructor) && o.constructor==Array) {
>> return true;
>> }
>> // It might be an array defined from another window object - check to
>> see if it has an Array's methods
>> if (typeof(o.join)=="function" && typeof(o.sort)=="function" &&
>> typeof(o.reverse)=="function") {
>> return true;
>> }
>> // As a last resort, let's see if index [0] is defined
>> return (o.length==0 || defined(o[0]));
>> };
>>
>> Suggestions?

>
> var myArray = new Array();
> myArray[0] = "Its an array";
> myArray[1] = "It really is an array!";
> alert(isArray('myArray'))
>
> IE7: false
> Opera 9: false
> Firefox 2.0: false


And now I know why after giving it some thought and thinking about it. I
passed the name of the array rather than the array itself. Might be
something to think about though. The possibility of passing the name
instead of the array itself.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

Julian Turner 12-15-2006 09:04 AM

Re: Robust isArray() ?
 

Matt Kruse wrote:

> Julian Turner wrote:
> > Could you could do a toString instead on the constructor, and check
> > that?

>
> I don't think so, because that can vary between browsers and doesn't return
> just a single string like "Array".


I take your point. I think it has been noted before that the results
of toString are implementation independent. However, as you are
testing for a positive, it could be another String to the bow (if you
will pardon the pun!).


[snip]
> > I note also that "arguments" in IE has "Object" as its constructor,
> > but "Array" in Opera or Firefox I think.

>
> The provided functions works in both cases.


Yes, it would, as you are testing for length etc.

> I guess one thing I'm also looking for is something that is most certainly
> NOT an array, but returns true with the provided function. Then, depending
> on if the test case is practical or not, I can re-think it. I don't think a
> perfect solution exists.


Hmm, what about this.

function falseArray()
{
this.length = 1;
this[0] = "False first element";
}

Can't think when you would encounter this though.

Regards

Julian



All times are GMT. The time now is 06:11 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57