Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > Robust isArray() ?

Reply
Thread Tools

Robust isArray() ?

 
 
VK
Guest
Posts: n/a
 
      12-15-2006
Matt Kruse wrote:
> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
> isArray function.


This sentence contains two mutually exclusive demands, because the most
robust and backwards-compatible way is (someObj instanceof Array) //
true / false

So the max you can ask is "let lesser robust and lesser
backwards-compatible but without instanceof" and this pretty much
renders the problem from a practical task into a mind game.

Also from the posted sample it is hard to say what are you looking for:

1) to determine if some object has JavaScript Array object in its
prototype chain (thus inherits the functionality of JavaScript Array).

2) to determine if some object implementing JavaScript Array
functionality by its own custom means.

3) to determine if some object has properties with the same names and
types as an Array instance would have (so for some reason assumed to
have the same functionality).

Whatever the real purpose is, the posted code accomplishes (up to some
extend) only the position (3).

///////////////

Check for the position (1)
To determine if some object has JavaScript Array object in its
prototype chain (thus inherits the functionality of JavaScript Array).

JavaScript implements the prototype-based inheritance. The prototype
chain for each new instance is being activated at the moment of
creation ("new SomeObject" call) and it is only side-connected (or more
often not connected at all) to the involved function-constructors. This
way [constructor] property check is irrelevant to the prototype matter.
I'm really disappointed to see *such* [constructor] usage in *your*
code. Once again I suggest to everyone willing to understand the
JavaScript object model to read and to study the article at
<http://blogs.msdn.com/ericlippert/archive/2003/11/06/53352.aspx>

The created prototype chain is immutable and it is the only robust and
natural way to check the object kind in JavaScript.

Note:
On Netscape and Gecko platforms it is possible to hack the chain using
the proprietary __proto__ property. It means then that someone is
actively preventing the object's determination by a 3rd party. Despite
technically possible, it is supported only on a relatively small amount
of UAs and it is more related with some "conspiracy theory" than with
any practical programming. At least it has no practical interest to me.

The obvious and natural way to check the prototype chain against some
known object is instanceof operator. It was specially made for it, so
there is absolutely no reason to substitute it with any home-made
tools.

instanceof operator is supported at least back to JavaScript 1.2
(Netscape 4.x) and JScript 5.0 (IE 5.0). This way I don't understand
what "backwards-compatible" issues could it possibly raise.

At the same time I know that there is some "opposition" to instanceof
usage in JavaScript. It is caused by the fact that some class-based
languages do have instanceof operator as well, so using instanceof in
JavaScript considered by some as "betraying the prototype environment"
. This is a silly allusion because instanceof in JavaScript and say
instanceof in Java share nothing but their names.

instanceof in JavaScript is in fact a "syntactic sugar" for
obj.prototype.isPrototypeOf(instance)

Note:
It is not in a connection with the topic, but as long as we started on
instanceof operator:
With its real mechanics revealed as
obj.prototype.isPrototypeOf(instance) it becomes clear why each
instance is also instanceof Object
ArrayObject instanceof Array; // true
ArrayObject instanceof Object; // true as well
The latter is true because any object has Object prototype in its
chain, so all objects could share the same basic Object functionality.
People who are not aware about the inheritance principles are getting
confused sometimes by this pseudo-"double nature" of JavaScript
objects. Some of them even consider it as some "failure" of instanceof
operator (to a great fun of anyone reading such statements).

To sum the things up, instanceof operator is the only one really
reliable object check tool specially made for it. It must be always
used - unless for pure sport one wants to support very ancient and not
used anymore platforms.


///////////////
Check for the position (2)
To determine if some object implementing JavaScript Array functionality
by its own custom means.

This is the most simple one: there cannot be such JavaScript object, so
there is no need for such check.

Note:
There can be DOM object with such functionality if it has the needed
behavior/binding attached.

While the answer itself is very simple, the question of why such object
is not possible may need some more explanations.

There are "fields" and "compound properties". A field is what it names
implies - a primitive data field one can set, get and (if allowed)
delete.
var obj = new Object;
obj.foo = 'bar';
Property "foo" in the sample above is a field.

Besides that there are compound property with getter and setter. The
core difference between compound property and field is that the value
itself stored internally as a separate private variable. The only way
to change it is by using getter and setter methods.
var arr = new Array(1,2,3);
window.alert(arr.length);
arr.length = 1;
In the sample above length is a compound property. By reading/assigning
its value we are really calling getter and setter methods, the value
itself is not directly accessible. Because any call to a compound
property goes only through a method, such properties have one very
important advantage over fields:

Compound properties allow to establish relations of any complexity
between property change / read actions and other methods and
properties. Say an assignment to the array length (thus usage of length
property setter) trigs the array elements removal if the new length is
smaller than the old one.

Now how is it all connected to a possible Array mimicking? The deal is
that the [length] is the *only one* compound property existing in the
basic JavaScript, everything else are fields.

Note:
Not all of authors do always understand the unique status of [length]
as the only one compound property in the entire language. They still
feel that there is "something" about [length] making it different from
say obj.foo. But because of lack of knowledge they limit the
explanations by "special property", "self-updating property" and the
like.

Moreover basic JavaScript does *not* allow to create new compound
properties. The [length] is only one and there cannot be any others
(again: in the basic scripting environment).

Now it becomes clear why there cannot be any "self-made" arrays:
because there is no way to implement the [length] property. You either
use *that* Array, or you have to use custom length() method instead of
length property.

This makes possible to implement a tedious "arrayness" check like:
function isArray(obj) {
var ret = false;
if (typeof obj.length == 'number') {
var len = obj.length;
obj[len] = 'probe';
ret = (len < obj.length);
delete obj[len];
}
return ret;
}
There is only one object in JavaScript physically ever capable to pass
the above check (where setting one property automatically reflected in
another property). This object will be either an array instance or an
object instance having Array.prototype somewhere in its prototype
chain.

At the same time I want to stress once again that this *tedious* and
*ridiculous* isArray check is not needed. JavaScript has specially made
instanceof operator for that. It also means that there is no need for
any custom functions like isArray(), isDate(), isRegExp() at all - if
(obj instanceof Something) does all of it.

It is possible of course to make a function like
function isArray(obj) {
return (obj instanceof Array);
}
and then later:
if (isArray(obj)) {
// make stuff
}
but it's getting too much similar to the infamous Java's trutherizer
, so I'm insistently discouraging anyone to go this way.

Note:
About the trutherizer (sadly enough based on a real life case) see for
instance
<http://mindprod.com/jgloss/unmainobfuscation.html>, sample 34
Actually the whole page as well as the whole section
<http://www.mindprod.com/jgloss/unmain.html> is a must-read for any
programmer, irrelevant of that programming language is being used.

To make a long story shorter: the only practical check in array could
be for the presence of particular methods.

Note:
It does not affect your particular case, but it has to be kept in mind.
While Gecko-based and many other browsers report type of native methods
as "function", Internet Explorer reports type of native methods for
JScript objects as "function" but type of native methods for DOM
objects as "object". Say typeof arrayObject.push will be "function" but
document.createElement will be "object" on IE. As I said it doesn't
affect you code but it has to be always kept in mind to avoid wrong
negatives.

So:
1) there is no need for isArray method in JavaScript unless you need to
obfuscate your code. Simply check
if (someObject instanceof Array) {
// needed actions
}
2) There can be a need to check for a particular method support, but
naturally it has to go in the head section for the Array prototype
itself.
function prepareEnvironment() {
if (typeof Array.prototype.push != 'function') {
Array.prototype.push = myCustomMethod;
}
// other preparative actions
}

 
Reply With Quote
 
 
 
 
Randy Webb
Guest
Posts: n/a
 
      12-15-2006
VK said the following on 12/15/2006 11:39 AM:
> Matt Kruse wrote:
>> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
>> isArray function.

>
> This sentence contains two mutually exclusive demands


No it doesn't.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
 
Reply With Quote
 
 
 
 
VK
Guest
Posts: n/a
 
      12-15-2006
> >> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
> >> isArray function.

> >
> > This sentence contains two mutually exclusive demands

>
> No it doesn't.


Cheking my math :

1) "most robust"
2) "no instanceof"

 
Reply With Quote
 
VK
Guest
Posts: n/a
 
      12-15-2006

VK wrote:
> > >> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
> > >> isArray function.
> > >
> > > This sentence contains two mutually exclusive demands

> >
> > No it doesn't.

>
> Cheking my math :
>
> 1) "most robust"
> 2) "no instanceof"


OK, if we want a IE 4.x or Netscape 3.x compatible solution, that the
"most robust" way will be the one with [length] autoupdate check (see
my first post in this thread).
But as I pointed in advance, it is a concept demonstration, so I'm
strictly opposed to see this code practically used anywhere, instead of
the conventional instanceof operator.

 
Reply With Quote
 
Randy Webb
Guest
Posts: n/a
 
      12-16-2006
VK said the following on 12/15/2006 12:11 PM:
>>>> I'm seeking the most robust and backwards-compatible (ie, no instanceof)
>>>> isArray function.
>>> This sentence contains two mutually exclusive demands

>> No it doesn't.

>
> Cheking my math :
>
> 1) "most robust"
> 2) "no instanceof"


As I know from reading 14 kazillion of your posts that English is not
your primary language I can see where you might be tempted to apply some
JRS logic to the statement. It is a combined requirement, not exclusive
requirements.

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
 
Reply With Quote
 
Richard Cornford
Guest
Posts: n/a
 
      12-16-2006
VK wrote:
> Matt Kruse wrote:
>> I'm seeking the most robust and backwards-compatible
>> (ie, no instanceof) isArray function.

>
> This sentence contains two mutually exclusive demands,


No it does not. "Most robust" is a relative term and
"backward-compatible" is a condition inside which relative robustness is
to be judged. It may be that given "backward-compatible" the most
relative robustness that can be achieved is not very robust at all, but
there will still be a "most robust".

> because the
> most robust and backwards-compatible way is (someObj
> instanceof Array) // true / false


If true that would be a pity as (someObj instanceof Array) is true for
an entire category of objects that are not arrays and cannot be treated
as arrays. That is, anything created with a constructor that has an
Array as its prototype or an object as a prototype that has an Array on
its prototype chain. Such objects would not have any special interest in
the assignment of 'array index' or "length" properties, and so would not
exhibit the Array-ness that is most likely the characteristic that needs
to be identified by the proposed function.

> So the max you can ask is "let lesser robust and lesser
> backwards-compatible but without instanceof"


Matt's English is much better than that, and there was nothing wrong
with the question as expressed, beyond its failure to explain what the
proposed - isArray - function was specifically intended to do.

> and this pretty much renders the problem from a
> practical task into a mind game.


Not rally, an actual specification for the function should reduce the
answer to a specific "it cannot be done" or code that does it one step.

> Also from the posted sample it is hard to say what are
> you looking for:


It is, but even harder for you as you have never really grasped what a
javascript array actually is.

> 1) to determine if some object has JavaScript Array
> object in its prototype chain (thus inherits the
> functionality of JavaScript Array).


The functionality of a javascript array cannot be inherited, only the
methods.

> 2) to determine if some object implementing JavaScript
> Array functionality by its own custom means.


No javascript object can do that, only host objects.

> 3) to determine if some object has properties with the
> same names and types as an Array instance would have
> (so for some reason assumed to have the same functionality).


No such assumption is valid as any object inheriting from an array will
have all the properties of an array but will not be an array itself.

> Whatever the real purpose is, the posted code accomplishes
> (up to some extend) only the position (3).




> ///////////////
>
> Check for the position (1)
> To determine if some object has JavaScript Array object in
> its prototype chain (thus inherits the functionality of
> JavaScript Array).
>
> JavaScript implements the prototype-based inheritance.
> The prototype chain for each new instance is being
> activated


Assigned

> at


After.

> the moment of creation


- of the instance of a new native ECMAScript object.

> ("new SomeObject" call)


The application of the - new - operator to a function reference starts a
process with at least two distinct stages so is better not though of a
'moment of creation', rather a process of creation where a certain
amount of important work (such as the creation of the actual object and
assignment of the prototype chain) precedes the execution of the
constructor function's body code.

> and it is only side-connected (or more often not
> connected at all) to the involved function-constructors.


It is actually very important to a constructor that the new object's
prototype chain has been established before the constructor body code is
executed. It allows a constructor to call the methods of the new object
as they have been defaulted on the object's prototype chain.

> This way [constructor] property check is
> irrelevant to the prototype matter. I'm really disappointed
> to see *such* [constructor] usage in *your* code.


It is only not-valid to reject all objects that do not have an Array
constructor as their - constructor - property as being Arrays in a world
where programmers are insane enough to re-assign values to -
Array.prototype.constructor - or assign - constructor - properties to
Array instances. Programmers who know that they are doing will just not
do that, but I can see why that test may concern you.

> Once again I suggest to everyone willing to understand
> the JavaScript object model to read and to study the
> article at
> <http://blogs.msdn.com/ericlippert/archive/2003/11/06/53352.aspx>


Advice on the understanding of javascript is not credible when it
originates from someone who so self evidently does not understand
javascript himself:-

<URL:
http://groups.google.com/group/comp...._frm/thread/64
ae20ba5c760c6/2820fbcd4b4ab7f8 >

> The created prototype chain is immutable and it is the
> only robust and natural way to check the object kind
> in JavaScript.


Knowing that another object is on the prototype chain of another object
is nowhere near sufficient in answering the question of identifying
objects that are Arrays and excluding objects that are not. You may be
able to dismiss all objects that do not have - Array.protoype - on their
prototype chain but you cannot then assume that the non-excluded set are
Arrays.

<snip>
> The obvious and natural way to check the prototype chain
> against some known object is instanceof operator. It was
> specially made for it, so there is absolutely no reason
> to substitute it with any home-made tools.


Beyond its inability to answer the pertinent question.

> instanceof operator is supported at least back to
> JavaScript 1.2 (Netscape 4.x)


This would be "supported at least back to JavaScript 1.2" in the sense
of 'introduced in JavaScript 1.4 and first available in Netscape 6+and
Mozilla 0.9'.

> and JScript 5.0 (IE 5.0). This way I don't understand
> what "backwards-compatible" issues could it possibly
> raise.


Not knowing when and where language features were introduced can make
seeing back-compatibility issues harder to spot.

> At the same time I know that there is some "opposition"
> to instanceof usage in JavaScript.


Such as observing that it is not very back-compatible and not necessary
at all and not very useful.

> It is caused by the fact that some class-based
> languages do have instanceof operator as well, so
> using instanceof in JavaScript considered by some
> as "betraying the prototype environment"


Nonsense.

> . This is a silly allusion because instanceof
> in JavaScript and say instanceof in Java share
> nothing but their names.


And - instanceof - is very useful in Java, particularly as it allows
code to verify the safety of something like casting to an interface. In
javascript there is no casting, being an instance of a 'class' that
implements an interface does not guarantee the ability to use that
interface on the object and runtime assignments to the - prototype -
properties of constructors can throw the - - instanceof - operator off,
i.e:-

function AnObject(){
;
}

var obj = new AnObject();
AnObject.prototype = {};

alert((obj instanceof AnObject)); // alerts false;

- so an object that is constricted with the right hand operand of -
instanceof - might still return false form that operation.

> instanceof in JavaScript is in fact a "syntactic sugar" for
> obj.prototype.isPrototypeOf(instance)


And the same issue with the runtime assignment to the constructor's
prototype applies here.

> Note:
> It is not in a connection with the topic, but as long as we
> started on instanceof operator:
> With its real mechanics revealed as
> obj.prototype.isPrototypeOf(instance)


That is not its real mechanics, that is an alternative that employs an
almost identical algorithm.

> it becomes clear why each
> instance is also instanceof Object
> ArrayObject instanceof Array; // true
> ArrayObject instanceof Object; // true as well
> The latter is true because any object has Object prototype
> in its chain, so all objects could share the same basic
> Object functionality. People who are not aware about the
> inheritance principles are getting confused sometimes by
> this


It was certainly a subject that was confusing you just two months ago
when you wrote:-

<URL:
http://groups.google.co.uk/group/com...c44f32b4566384
53 >

- but since I explained it to you there you seem to have started to
grasp prototype based inheritance. Though you still have some way to go.
I would anticipate another two years before you rid yourself of your
remaining misconceptions on the subject and get a real handle on the
issue (base on your not having got it after your first ten years of
using javascript).

> pseudo-"double nature" of JavaScript objects.


It would speed your gaining an understanding of javascript is you would
refrain form making up your own jargon. It just leaves you talking a
different language from everyone else, and that will make understanding
what you are told difficult.

> Some of them even consider it as some "failure" of
> instanceof operator (to a great fun of anyone reading
> such statements).


You realise that most of the time what you perceive as the attitudes of
others are in fact just the consequences of your not understanding what
you are being told by the better informed. I have never seen any
evidence of anyone (at all) expressing this belief. And that is often a
common thread in your posts, where you start going on about how people
are concerned with this or that when in reality nobody is even
interested in whatever it is you are whittering on about. A case in
point is in:-

<URL:
http://groups.google.co.uk/group/com...3bc6c90a43d991
0f >

- where you start going on about:-

| This is the point where different amateurish manuals starting
| to advise do not use unary minus: which is a 100% pure b.s. of
| course because at no circumstances the program *logic* can be
| affected by external textual parser.

- in the context of using the pre-decrement operator (not unary minus)
with script code inside <!-- ... --> comments in an XML file. This
impression of yours is a complete fantasy of your own creation because
in XML comments may be stripped from the source prior to parsing, and so
nobody is ever going to wrap them round content that is supposed to be
data, and doing so would effectively remove the data from the XML. There
is not, and never has been (outside of your own head), any issue with
using pre/post decrement operators in that context because that context
is itself a fiction.

> To sum the things up, instanceof operator is the only
> one really reliable object check tool specially made
> for it.


Or it is a non-back-compatible operator that may be able to exclude
objects that could not be Arrays but cannot in itself verify that any
given object is an Array.

> It must be always used


It is inadequate for the task in hand. And you yourself pointed out
that - isPrototypeOf - can produce equivalent results (so "must be used"
is false anyway), but while you cannot feature test for support for an
operator in the language you can feature test for a method of objects.

> - unless for pure sport one wants to support very ancient
> and not used anymore platforms.
>
> ///////////////
> Check for the position (2)
> To determine if some object implementing JavaScript Array
> functionality by its own custom means.
>
> This is the most simple one: there cannot be such JavaScript
> object, so there is no need for such check.


In the same way as your preceding option could not exist in javascript
(Array functionality cannot be inherited).

> Note:
> There can be DOM object with such functionality if it has
> the needed behavior/binding attached.


There can also be host object with the Array functionality (and language
extensions).

> While the answer itself is very simple, the question
> of why such object is not possible may need some more
> explanations.


It is fairly simple to explain, and follows from the inability of client
side code to replace the object's internal [[Put]] method. While it
would be theoretically possible to use the - watch - or -
__defineSetter__ - extensions in JavaScript(tm) to reproduce the side
effects of assignments to all possible 'array index' properties and
the - length - property of an object (and so fully reproduce the
behaviour required of the internal [[Put]] method on a custom object the
very large number of possible 'array index' properties that would need
to be watched would make the creation of such an object very time
consuming and probably a practical impossibility due to restrictions in
available memory.

> There are "fields" and "compound properties".


Ah, you are going to do one of your infamous 'off the top of your head'
fantasies.

> A field is what it names implies - a primitive data field
> one can set, get and (if allowed) delete.
> var obj = new Object;
> obj.foo = 'bar';
> Property "foo" in the sample above is a field.
>
> Besides that there are compound property with getter and setter.
> The core difference between compound property and field is that
> the value itself stored internally as a separate private
> variable. The only way to change it is by using getter and
> setter methods.
> var arr = new Array(1,2,3);
> window.alert(arr.length);
> arr.length = 1;
> In the sample above length is a compound property. By
> reading/assigning its value we are really calling getter
> and setter methods, the value itself is not directly
> accessible. Because any call to a compound property goes
> only through a method, such properties have one very
> important advantage over fields:
>
> Compound properties allow to establish relations of any
> complexity between property change / read actions and other
> methods and properties. Say an assignment to the array
> length (thus usage of length property setter) trigs the
> array elements removal if the new length is smaller than
> the old one.


A side effect following from an assignment to a named property.

> Now how is it all connected to a possible Array mimicking?


Oh, do tell.

> The deal is that the [length] is the *only one* compound
> property existing in the basic JavaScript, everything else
> are fields.


The only one? So no assignment to any other property will ever have a
side effect on a property that is not the subject of the assignment?
That would be an inevitable consequence of the mechanism you are
describing where the only " compound property" in the entire system was
the - length - property of array objects.

> Note:
> Not all of authors do always understand the unique status of
> [length]


Here you go again, attributing beliefs to others where no evidence
exists that anyone has these beliefs.

> as the only one compound property in the entire language.


You said it again " one compound property in the entire language", so
defiantly no other assignments will have side effects, no matter what.

> They still feel that there is "something" about [length]
> making it different from say obj.foo. But because of lack of
> knowledge they limit the explanations by "special property",
> "self-updating property" and the like.


Who does this? The informed attribute all special array behaviour
relating to assignment to the special internal [[Put]] method of arrays.

> Moreover basic JavaScript does *not* allow to create new
> compound properties. The [length] is only one and there
> cannot be any others


That is three times, we can be very certain that the varsity of this
'explanation' is tied 100% to the 'fact' that assignment operations to
any other property of any object in the system can have a side effect on
another property. There is no question that this a matter of
interpretation, a mistranslation, or a misquote; if any other assignment
can be demonstrated as having a side-effect in standard javascript this
entire 'explanation' is just false (that it is the 'off the top of your
head' fantasy that I suspected from the outset).

> (again: in the basic scripting environment).


Fine.

> Now it becomes clear why there cannot be any "self-made"
> arrays: because there is no way to implement the [length]
> property.


Well, with the - watch - extension it would be entirely possible to
implement an array-like length property, Granted that is not in the
basic scripting language, but it does raise a significant objection to
your 'explanation' above, because while it would be trivial to implement
an array like - length - property on any object with the - watch -
method (explicitly script the side effects of assignments to the length
property) it would still not be practical to implement an array like
object with the - watch - method.

The problem is that that is not just one property that may have side
effect when an assignment is made, each array has (2 to the power of 32)
such properties. An assignment to any 'array index' property, where the
index is grater than or equal to, the length property will have a side
effect on the - length - property, it will increase it. It is the
impracticality of using the - watch - method to trigger any possible
side-effect for each such assignment that precludes an emulation of an
array with other object.

However, your explanation of a single "compound property" is not only
failing to explain these other side-effect producing assignments, but
also suffers from the same practical limitation, as if a property
specific setter is the means of producing the side effect your
explanation needs (2 to the power of 32) additional setters, and that is
going to be impractical even in native code.

The explanation if much simpler; it is that all javascript objects have
an internal [[Put]] method that is used for assignments, that this
method is passed the property name and the value that is to be assigned,
and that Arrays have a single special [[Put]] method that examines the
property name to see if it is an array index property name or "length"
and if it is performs the appropriate side-effect on the Array object to
which the [[Put]] method belongs. That is how the language specification
say javascript should behave, and is sufficient to fully explain the
behaviour observed.

> You either use *that* Array, or you have to use custom
> length() method instead of length property.
>
> This makes possible to implement a tedious "arrayness"
> check like:
> function isArray(obj) {
> var ret = false;
> if (typeof obj.length == 'number') {
> var len = obj.length;
> obj[len] = 'probe';


Isn't this 'test' predicated on the fact that assigning to an 'array
index' property of an Array does produce a side-effect on its - length -
property? Where you not just 'explaining' how that was not possible in
javascript because the 'array index' properties are not your "compound
properties"? While I don't expect someone as irrational as you to
produce internally consistent posts you could at least make an effort
not to obviously contradict yourself.

> ret = (len < obj.length);
> delete obj[len];
> }
> return ret;
> }


Any test that is intended to differentiate between objects that are
arrays and objects that are not arrays should not be designed to
permanently alter the object that is tested. Here any array that passes
the test will find itself with a - length - property that is one longer
than it was to start with, which is pretty important given what an array
is. (All javascript objects, including arrays, use the same internal
[[Delete]] method, and it has no side-effects).

> There is only one object in JavaScript physically ever
> capable to pass the above check
> (where setting one property automatically
> reflected in another property).


Weren't you saying that only assignments to the - length - property has
such side effects? While this property has a name that is the
type-converted to string equivalent of the value of the - length -
property.

> This object will be either an array instance


Or a host object with array-like behaviour.

> or an object instance having Array.prototype somewhere
> in its prototype chain.


Nonsense. Having an array in an object's prototype chain does not confer
this "side-effect on assignment to 'array index' properties" on such an
object, because the internal [[Put]] method is a property of each
individual object and cannot be inherited. Any object that inherits from
an Array can still only have the standard object [[Put]] method, which
does not do side effects when used.

> At the same time I want to stress once again that this
> *tedious* and *ridiculous* isArray check is not needed.



Not that test, but a better implementation of a similar test (that does
not leave the objects tested altered by the testing) would be the only
type of testing that would be capable of identifying objects which
behaved as if they had the special Array [[Put]] method.

function isArray(obj){
var len, res = false;
if(
(typeof (len = obj.length) == 'number')&&
((len >>> 0) == len)&&
(typeof obj[len] == 'undefined')
){
obj[len] = null;
res = (obj.length > (obj.length = len));
delete obj[len];
}
return res;
}

- would be better, but still suffers from potentially moving an
inherited - length - property form the prototype of a non-array object
onto the object itself.

> JavaScript has specially
> made instanceof operator for that.


Having made the mistake of thinking that array-ness could be inherited
through the protyo00e chain you might think that.

> It also means that there is no need for any custom
> functions like isArray(), isDate(), isRegExp() at
> all - if (obj instanceof Something) does all of it.


So maybe it is a pity that it does none of it.

<snip>
> To make a long story shorter: the only practical check
> in array could be for the presence of particular methods.

<snip>

This would be "practical" in the sense of not ending up knowing whether
the object in question was an array or not (very similar to using
instanceof in that regard).

Richard.


 
Reply With Quote
 
Randy Webb
Guest
Posts: n/a
 
      12-16-2006
Richard Cornford said the following on 12/16/2006 1:40 AM:
> VK wrote:
>> Matt Kruse wrote:
>>> I'm seeking the most robust and backwards-compatible
>>> (ie, no instanceof) isArray function.


<snip>

> Matt's English is much better than that, and there was nothing wrong
> with the question as expressed, beyond its failure to explain what the
> proposed - isArray - function was specifically intended to do.


The intent, to me, was very apparent in that the function is
specifically intended to determine if an object is an array or not and
do it in the most robust way possible while retaining as much backwards
compatibility as possible.

Or, do you expect to get a dissertation from anyone asking a question?

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
 
Reply With Quote
 
Richard Cornford
Guest
Posts: n/a
 
      12-16-2006
Randy Webb wrote:
> Richard Cornford said the following on 12/16/2006 1:40 AM:
>> VK wrote:
>>> Matt Kruse wrote:
>>>> I'm seeking the most robust and backwards-compatible
>>>> (ie, no instanceof) isArray function.

>
> <snip>
>
>> Matt's English is much better than that, and there was nothing
>> wrong with the question as expressed, beyond its failure to
>> explain what the proposed - isArray - function was specifically
>> intended to do.

>
> The intent, to me, was very apparent in that the function is
> specifically intended to determine if an object is an array or not

<snip>

That was my impression too, but there was no specification of what being
an array means in this context. And that question is rendered more
unclear by Matt's subsequent suggestion that - arguments - objects
should be included (even though it does not have the methods or an
array, the special [[Put]] method and assignments to 'array index'
properties of an - arguments - object are specified as having side
effects on named properties of the Activation/Variable object for which
it is the - arguments - value).

Richard.



 
Reply With Quote
 
webEater
Guest
Posts: n/a
 
      12-16-2006

Matt Kruse schrieb:

> 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


I am impressed by your discussion, but what I am using and what is
working an all current browsers is:

isArray = function(object) {
return object instanceof Array;
};

 
Reply With Quote
 
webEater
Guest
Posts: n/a
 
      12-16-2006

webEater schrieb:

> Matt Kruse schrieb:
>
> > 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

>
> I am impressed by your discussion, but what I am using and what is
> working an all current browsers is:
>
> isArray = function(object) {
> return object instanceof Array;
> };


I mean IE 5.5+, Opera 7+, Mozilla, FF 1+, Safari 1/2, ..

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Robust CSS dorayme HTML 10 06-20-2006 10:47 PM
robust iterator implementation Martin Smith C++ 4 01-25-2005 11:12 AM
robust clean-up with SIGTERM (was Re: Again, how to write a cleanup function for a module in C ) Jane Austine Python 2 08-16-2003 04:01 AM
ANN: EmPy 3.0.4 -- A powerful and robust templating system for Python Erik Max Francis Python 0 08-08-2003 03:53 AM
ANN: EmPy 3.0.3 -- A powerful and robust templating system for Python Erik Max Francis Python 0 07-09-2003 10:11 PM



Advertisments