By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
437,569 Members | 1,181 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 437,569 IT Pros & Developers. It's quick & easy.

Its the isArray() function thing again

P: n/a
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
Jul 26 '08 #1
Share this Question
Share on Google+
18 Replies


P: n/a
On Jul 26, 3:03 pm, "Aaron Gray" <ang.use...@gmail.comwrote:
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...ison_Operators

Any critisisms, advances, or advice ?
What's wrong with

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

http://developer.mozilla.org/en/docs...nceof_Operator

Peter
Jul 26 '08 #2

P: n/a
"Aaron Gray" <an********@gmail.comwrites:
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.'
Jul 26 '08 #3

P: n/a
Aaron Gray meinte:
But I am not sure when 'in' was actually introduced.
Then there was the advice to use === rather than ==, but I dont know when
that was introduced too
Before he does it:
http://pointedears.de/scripts/es-matrix/

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
Jul 26 '08 #4

P: n/a
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
Jul 26 '08 #5

P: n/a
"Lasse Reichstein Nielsen" <lr*@hotpop.comwrote in message
news:4p**********@hotpop.com...
"Aaron Gray" <an********@gmail.comwrites:
>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

Jul 26 '08 #6

P: n/a
On Jul 26, 3:36*pm, Lasse Reichstein Nielsen <l...@hotpop.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrites:
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
Jul 26 '08 #7

P: n/a
On Jul 26, 4:52 pm, dhtml <dhtmlkitc...@gmail.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrites:
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
Jul 27 '08 #8

P: n/a
On Jul 27, 9:52*am, dhtml <dhtmlkitc...@gmail.comwrote:
On Jul 26, 3:36*pm, Lasse Reichstein Nielsen <l...@hotpop.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrites:
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
Jul 27 '08 #9

P: n/a
On Jul 26, 7:10*pm, RobG <rg...@iinet.net.auwrote:
On Jul 27, 9:52*am, dhtml <dhtmlkitc...@gmail.comwrote:
On Jul 26, 3:36*pm, Lasse Reichstein Nielsen <l...@hotpop.comwrote:
"Aaron Gray" <ang.use...@gmail.comwrites:
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
Jul 27 '08 #10

P: n/a
"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
Jul 27 '08 #11

P: n/a
On Jul 27, 5:55*pm, Peter Michaux <petermich...@gmail.comwrote:
>
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.
Jul 27 '08 #12

P: n/a
On Jul 27, 7:02*pm, Jorge <jo...@jorgechamorro.comwrote:
On Jul 27, 5:55*pm, Peter Michaux <petermich...@gmail.comwrote:
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
https://mail.mozilla.org/pipermail/e...hread.html#324
https://mail.mozilla.org/pipermail/e...read.html#3227

--Jorge.
Jul 27 '08 #13

P: n/a
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.

Jul 27 '08 #14

P: n/a
On Jul 27, 11:53*pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
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.
Jul 27 '08 #15

P: n/a
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.

Jul 27 '08 #16

P: n/a
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.

Jul 27 '08 #17

P: n/a
On Jul 28, 12:26*am, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:
>
It is probably best if I don't comment on that.
Thanks. I also know about *that* contest.

--Jorge.
Jul 27 '08 #18

P: n/a
On Jul 27, 3:22*pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
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.
Jul 28 '08 #19

This discussion thread is closed

Replies have been disabled for this discussion.