PDA

View Full Version : empty array elm type?



rnd me
Oct 22nd, 2009, 08:44 PM
What type of variable is an empty array element?

i thought it was undefined, but i noticed that they have different behavior than undefined does:



var r=Array(1);
var s=r.concat([0,"",null,undefined]);

alert (s.toSource()) //==="[, 0, "", null, (void 0)]"


typeof s[0] //==="undefined"
typeof s[4] //==="undefined"



as you can see, 0 and 4 both === undefined.
yet, they don't have the same toSource()...

why?

is this special type named anything specific?
or more importantly, can it be detected outside of an array as being distinct from undefined?

EDIT:
im thinking this would be the same type as ({}).nonProp ...

i guess the question is actually, "can you tell the difference between uninitialized and undefined"?

Old Pedant
Oct 22nd, 2009, 09:02 PM
Well, consider this:


var a = new Array();
a[2000000000] = "foo";
alert( a[2000000000] );

*CLEARLY* JavaScript doesn't allocate memory for 2 billion array elements!

JavaScript arrays are *not* like arrays in other languages.

There truly is no (effective) difference between doing:


var a = new Array();
a[2000000000] = "foo";
a["zamboni"] = "rules";

There really are only two array elements in that array. And each is accessible. And of course if you ask for

alert( a[0] );
or
alert( a["bar"] );
you get the same thing: An undefined element.

So there really *isn't* any s[0] element in your array, which is what toSource() is (sort of) telling you.

It's only when you force JS to "find" that element via
alert( typeof s[0] ); that it has to create *something* to get the typeof and so creates an undefined value for you.

So... I don't know how you discover that a given array element is non-existent, as opposed to being simply undefined, because as soon as you specify the element by name/number, JS has to create something and it creates an undefined value.

The only other option would have been for JS to throw an error if you accessed a non-existent element, but of course that would seriously hamper a lot of operations that depend on iterating through arrays by element number.

It's a good question. If you figure out the answer, I'd like to know it.

rnd me
Oct 22nd, 2009, 09:19 PM
i think i've figured out that my question doesn't make sense after a lot of consideration. It's just an empty property, not undefined per se, only evaluates to undefined.



Well, consider this:

So... I don't know how you discover that a given array element is non-existent, as opposed to being simply undefined, because as soon as you specify the element by name/number, JS has to create something and it creates an undefined value.
It's a good question. If you figure out the answer, I'd like to know it.

that's actually pretty easy, and you made me answer my own question by pounding out a firebug example.

"in" checks for an existing property, which for arrays, is usually an integer.



var r=Array();
r[100]=true;

alert(50 in r) //false
alert(100 in r)//true

so far, as expected.

here's where it get's interesting, and shows that un-init !== undefined:

var r=Array();
r[100]=undefined;
alert(100 in r)//true

Like you mention, the array doesn't store 99 empty slots, but it adds those commas to its toString/Source() version so as to re-create the logical structure of the array as we use it most often.

in this respect, for-in might be BETTER for empty-prone arrays, provided you block protos and props:


var r=Array();
r[5000]="Dan";
var i=0;
for(it in r){if(r.hasOwnProperty(it) && !isNaN(it) ){
i++;
}}
alert(i)//===1

there's only one cycle instead of 5000.
Array.map also checks for each index between 0 and length to be defined before firing, so it's no better.
i always rejected for in with arrays, but i guess it does have legitimate uses after all.

Old Pedant
Oct 22nd, 2009, 10:12 PM
FWIW, the "in" trick works for non-integer element checks:


var r=Array();
r[100]=true;
r["foo"]="bar";

alert(50 in r) //false
alert(100 in r)//true
alert("foo" in r) // true
alert("woof" in r) // false


So you are very right. This would appear to be the only practical way to make the check.

Nice to know.

Kor
Oct 23rd, 2009, 03:04 PM
rnd me, it looks like you are to circle through a sorted array, but you want to treat it as an unsorted one.

If, by hazard, your array has or has to have the elements:

r[100]=true;
r["foo"]="bar";

It seems more logical for me to define that array, from the very beginning, as an unsorted array (as an object). If so, all your consideration about the loops length remains without support:


var r={}; // set the variable as an object (unsorted array)
r[100]=true;
r["foo"]="bar";
var i=0;
for(prop in r){
i++;
}
alert(i);

rnd me
Oct 24th, 2009, 12:08 AM
It seems more logical for me to define that array, from the very beginning, as an unsorted array (as an object). If so, all your consideration about the loops length remains without support


what i said was:


"for-in might be BETTER for empty-prone arrays, provided you block protos and props"

an object is not an unsorted array.
an array is an object that happens to provide prototype methods for integer properties between 0 and the array's other special property, .length.

If i didn't have keys, how would i use an object?

Most importantly, how would i retain the ability to efficiently run the js1.6 array methods i can't live without on an object?

Kor
Oct 24th, 2009, 04:56 PM
an object is not an unsorted array.

Right. Sorry my mistype. It is an associative array.


an array is an object that happens to provide prototype methods for integer properties between 0 and the array's other special property, .length.

Well, yes and no. I would rather say that both arrays and objects are data structures. For a reason or another I prefer to treat them somehow separately, in a JSON (http://json.org/) manner


If i didn't have keys, how would i use an object?

I really did not quite understand this question. If you don't know the keys, you may simply find them within a for (property in object) loop. Or you meant something else?