|
|||
|
Matt Kruse wrote:
> 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? > If by "array" you mean something that can be iterated over with the following construct: for(var index = 0; index < myArray.length; index++) alert(myArray[index]); without error, then any object that has a non-negative numeric 'length' property will satisfy your criteria. As for your last test: return (o.length==0 || defined(o[0])); Consider the following: var x = new Array(); x[5] = "garbanzo"; alert(typeof n[0]); //"undefined" in FF 1.5 I would instead check whether o[o.length - 1] is defined - if it's not, then o has no reason to have length of o.length (however there is nothing preventing you from explicitly setting the length of the array). In the above example: var x = new Array(); x[5] = "garbanzo"; alert(typeof n[n.length - 1]); //"string" Jeremy |
|
|
||||
|
||||
|
|
|
|||
|
Jeremy wrote:
> If by "array" you mean something that can be iterated over with the > following construct: > for(var index = 0; index < myArray.length; index++) > alert(myArray[index]); > without error, then any object that has a non-negative numeric > 'length' property will satisfy your criteria. I suppose, but that doesn't mean that numeric indexes from 0..(length-1) of the object are intended to hold any meaningful data. > As for your last test: > return (o.length==0 || defined(o[0])); > Consider the following: > var x = new Array(); > x[5] = "garbanzo"; > alert(typeof n[0]); //"undefined" in FF 1.5 That's why this case would already be trapped by the code about the final test. > I would instead check whether o[o.length - 1] is defined - if it's > not, then o has no reason to have length of o.length This might be logically true, but one could easily do: var empty = [,,,,,]; -- Matt Kruse http://www.JavascriptToolbox.com http://www.AjaxToolbox.com |
|
|||
|
Richard Cornford wrote: > That is the basis of the > test, but deleting the 'array index' member you have added to the array > does not have any side-effects on the array's - length - property so it > remains one greater then it was to start with. Hum... indeed. That's kind of a silly behavior I did not notice before - as I never used delete on array elements. IMO delete should work the same way as delete someObject.someProperty - not keeping someProperty with undefined value but _delete_ it as it never existed. Well, it's easy to fix: function isArray(obj) { var ret = false; var len = 0; if (obj) { len = parseInt(obj.length, 10); if (len == len) { obj[len] = 'probe'; ret = (len < obj.length); obj.length = len; } } return ret; } > Didn't you see my other reply to that test code with the standard > javascript object that fools your " absolutely robust" into believing it > is an array without its even inheriting the methods or an array? I > suppose I had better post it again for your benefit:- > > function AnObject(){ > ; > } > AnObject.prototype = { > length:{ > count:0, > valueOf:function(){ > return this.count++; > }, > toString:function(){ > return '0'; > } > } > }; > var obj = new AnObject(); > > alert(('isArray(obj) = '+isArray(obj)));//alerts isArray(obj) = true; What browser did you test it on? Of course it fails (false). As I said, there is no technical way to implement compound property within ECMAScript 3rd ed. It's not a teasing for an intellectual challenge, just a constatation of a fact. Respectively this isArray is absolutely rubust yet absolutely not needed with instanceof alive. |
|
|||
|
VK wrote:
> Richard Cornford wrote: >> That is the basis of the >> test, but deleting the 'array index' member you have >> added to the array does not have any side-effects on >> the array's - length - property so it remains one >> greater then it was to start with. > > Hum... indeed. That's kind of a silly behavior I did not > notice before - as I never used delete on array elements. And you only needed to be told why your original - isArray - function was inadequate three times before you tried it for yourself. > IMO delete should work the same way as delete > someObject.someProperty - not keeping someProperty > with undefined value but _delete_ it as it never existed. That is exactly what - delete - does do. I don't know what exactly passes as testing with you but it doesn't appear to leave yo0u any better informed. > Well, it's easy to fix: > > function isArray(obj) { > var ret = false; > var len = 0; > > if (obj) { > len = parseInt(obj.length, 10); > if (len == len) { > obj[len] = 'probe'; > ret = (len < obj.length); > obj.length = len; > } > } > > return ret; > } You really don't understand what the code you write does, and even when your faults are pointed out you just don't know how to correct them. You have change code that modifies the - length - property of all the arrays that are exposed to it into code that adds a new (or changes an existing) property to (on) every non-array object it encounters that has a numeric - length - property (which, at minimum, includes all String and Function objects, plus many custom objects). A test function really should not permanently modify the objects that it tests. >>> It is absolutely not possible within the frame of >>> ECMAScript 3rd ed. >> >> Didn't you see my other reply to that test code with >> the standard javascript object that fools your " absolutely >> robust" into believing it is an array without its even >> inheriting the methods or an array? I suppose I had better >> post it again for your benefit:- >> >> function AnObject(){ >> ; >> } >> AnObject.prototype = { >> length:{ >> count:0, >> valueOf:function(){ >> return this.count++; >> }, >> toString:function(){ >> return '0'; >> } >> } >> }; >> var obj = new AnObject(); >> >> alert(('isArray(obj) = '+isArray(obj)));//alerts isArray(obj) = true; > > What browser did you test it on? Firefox, Opera and IE (though it is pure ECMAScript so would be expected to work with all anyway). Why didn't you test it? Or why couldn't you manage to perform such a simple test effectively? > Of course it fails (false). When the - isArray - function is the function that you posted and declared "absolutely robust", that was:- | function isArray(obj) { | var ret = false; | if ((obj) && (!(isNaN(parseInt(obj.length))))) { | var len = parseInt(obj.length, 10); | if (len == obj.length) { | obj[len] = 'probe'; | ret = (len < obj.length); | delete obj[len]; | } | } | return ret; | } - the result is exactly as I described; the alert is 'isArray(obj) = true'. You could verify that by trying it yourself, as anyone else can. > As I said, there is no technical way to implement > compound property within ECMAScript 3rd ed. As your whole "compound property" thing was a fiction with no reality outside your own head anything you say on the subject is irrelevant. > It's not a teasing for an intellectual challenge, > just a constatation of a fact. It is a fiction. > Respectively this isArray "This isArray"? Not the previous one? > is absolutely rubust So there can be no object for which - isArray(obj) - (where - isArray - is your new version rather than the previous version that reported - true - for the object I already posted) returns true? One of the consequences of your basing your conception of javascript on your ludicrous fictions is that you end up making statements that are easily demonstrated as false. This object:- function AnObject(){ ; } AnObject.prototype = { length:{ valueOf:function(){ return 1; }, toString:function(){ return '0'; } } }; var obj = new AnObject(); alert(('isArray(obj) = '+isArray(obj)));//alerts isArray(obj) = true - returns - true - from your newest "absolutely robust" array test, even though it is clearly not an array. It does so for precisely the same reason as my previous object returned true from your previous - isArray - test. And if you had bothered to test my previous object with your previous test you may have seen the obvious truth that would have suggested that you not label this test as any more "absolutely robust" as your last easily fooled test. > yet absolutely not needed with instanceof alive. If you had understood my criticism of your use of - instanceof - in this context you would be able to see why that would not help anyway. Richard. |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| t-test: robust standard error | ptv-sas@sociology.osu.edu | Newsgroup comp.soft-sys.sas | 0 | 10-08-2005 01:43 AM |