I've had a bit of a wakeup to the nature of JavaScript array indexes recently. Pursuing it, I found the following (I'm working with Node.js in interpretive mode here):
var x=[];
x['a']='a';
console.log(x); // Yields [ a: 'a' ]
console.log(x.length); // yields 0 not 1
x[1]=1;
console.log(x); // Yields [ , 1, a: 'a' ]
console.log(x.length); // Yields 2 not 3 (one for empty 0 space, one for the occupied 1 space)
Is a: 'a'
really what it looks like - an object property embedded in an array - and, thus, isn't counted in the array property .length
?
No, it doesn't make sense to use array to store values in a (string)key when you cannot use the string keys in methods like forEach , map and array related methods. It'll make things complicated but still if you want to do it then use an object instead.
Characters in a string are indexed from left to right. The index of the first character is 0 , and the index of the last character—in a string called stringName —is stringName.length - 1 . If the index you supply is out of this range, JavaScript returns an empty string.
JavaScript does not support associative arrays. You should use objects when you want the element names to be strings (text). You should use arrays when you want the element names to be numbers.
JavaScript arrays are zero-indexed: the first element of an array is at index 0 , the second is at index 1 , and so on — and the last element is at the value of the array's length property minus 1 .
In JavaScript, arrays are just objects with some special properties, such as an automatic length
property, and some methods attached (such as sort
, pop
, join
, etc.). Indeed, a
will not be counted in your array, since the length
property of an array only stores the amount of elements with a property name that can be represented with a 32-bit positive integer.
And since arrays always automatically define every numbered element up to the highest element with a positive 32-bit int property name, this effectively means the length
property stores 1 higher than the element with the highest 32-bit integer as a property name. Thanks @Felix Kling for correcting me about this in the comments.
Adding properties such as a
is not forbidden at all, but you should watch out with them, since it might be confusing when reading your code.
There's also a difference in walking through the elements in the array:
To walk through all the numbered elements:
for (var i=0; i<myArray.length; i++) {
//do something
}
To walk through every property that's not built-in:
for (var i in myArray) {
//do something
}
Note that this loop will also include anything that's included from Array.prototype
that's not a built-in method. So, if you were to add Array.prototype.sum = function() {/*...*/};
, it will also be looped through.
To find out if the object you're using is indeed an array, and not just an object, you could perform the following test:
if (Object.prototype.toString.call(myObject) === '[object Array]') {
//myObject is an array
} else if (typeof myObject === 'object') {
//myObject is some other kind of object
}
See @artem's comment: myObject instanceof Array
might not always work correctly.
That's correct, and it's a good illustration of the fact that that new Array you've created is really just a special kind of Object. In fact, typeof []
is 'object'
! Setting a named property on it (which might be written more cleanly here as x.a = 'a'
) is really setting a new property to the object wrapper around your "real" array (numbered properties, really). They don't affect the length property for the same reason that the Array.isArray
method doesn't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With