Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array length and undefined indexes

Tags:

I just want to understand how Javascript arrays work but I have a complicated problem here.

First I created my array:

var arr = []; 

And set some elements in it:

arr[5] = "a thing"; arr[2] = undefined; 

I thought that I should have an array of size 2, because I only have two objects at 2 specific indexes. So I tested it with the .length property of arrays:

document.write(arr.length + "<br>"); 

The result, interestingly, is 6. But it must contain two items. How can its size be 6? It is probably related with the latest index that I used, here arr[5] = "a thing";

I then tried to loop over it:

var size = 0; for(var x in arr){  size++;    } 

And the size variable is now 2. So, what I learned from this: if I use a for in loop, I will calculate how many properties are in it, not its last index.

But if I try to document.write(arr[4]) (which is not set yet), it writes undefined.

So why is arr[2] counted in the for..in loop, but not arr[4]?

Let me answer my question: what I was thinking about typeof undefined == undefined which is amazingly true. But this is JavaScript, we need to play with it using his own rules :)

jsFiddle and snippet below.

var arr = [];    arr[5] = "a thing";  arr[2] = undefined;  document.write(arr.length + "<br>");    var size = 0;  for(var x in arr){   size++;     }    document.write(size + "<br>");    document.write(arr[4] + "<br>");
like image 869
Ahmet Can Güven Avatar asked Jul 05 '15 22:07

Ahmet Can Güven


2 Answers

Note: Array indexes are nothing but properties of Array objects.

Quoting MDN's Relationship between length and numerical properties section,

When setting a property on a JavaScript array when the property is a valid array index and that index is outside the current bounds of the array, the engine will update the array's length property accordingly.

Quoting ECMA Script 5 Specification of Array Objects,

whenever a property is added whose name is an array index, the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted

So, when you set a value at index 5, JavaScript engine adjusts the length of the Array to 6.


Quoting ECMA Script 5 Specification of Array Objects,

A property name P (in the form of a String value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232−1.

So, in your case 2 and 4 are valid indexes but only 2 is defined in the array. You can confirm that like this

arr.hasOwnProperty(2) 

The other indexes are not defined in the array yet. So, your array object is called a sparse array object.

So why arr[2] is counted in for..in loop and not arr[4] is not counted?

The for..in enumerates all the valid enumerable properties of the object. In your case, since only 2 is a valid property in the array, it will be counted.

But, when you print arr[4], it prints undefined, because JavaScript will return undefined, if you try to access a property which is not defined in an object. For example,

console.log({}['name']); // undefined 

Similarly, since 4 is not yet defined in the arr, undefined is returned.


While we are on this subject, you might want to read these answers as well,

  • Why doesn't the length of the array change when I add a new property?

  • JavaScript 'in' operator for undefined elements in Arrays

like image 144
thefourtheye Avatar answered Sep 22 '22 04:09

thefourtheye


There’s a difference between a property that has the value undefined and a property that doesn’t exist, illustrated here using the in operator:

var obj = {     one: undefined };  console.log(obj.one === undefined); // true console.log(obj.two === undefined); // true  console.log('one' in obj); // true console.log('two' in obj); // false 

When you try to get the value of a property that doesn’t exist, you still get undefined, but that doesn’t make it exist.

Finally, to explain the behaviour you see: a for in loop will only loop over keys where that key is in the object (and is enumerable).

length, meanwhile, is just adjusted to be one more than whatever index you assign if that index is greater than or equal to the current length.

like image 43
Ry- Avatar answered Sep 21 '22 04:09

Ry-