Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript arrays: string indexed items

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?

like image 754
Matt Murphy Avatar asked Dec 19 '14 19:12

Matt Murphy


People also ask

Does array support string indexing in JavaScript?

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.

Are strings indexed in JavaScript?

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.

Can you have an array of strings in JavaScript?

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.

Are JavaScript arrays indexed?

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 .


2 Answers

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.

like image 116
Joeytje50 Avatar answered Sep 21 '22 16:09

Joeytje50


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.

like image 33
OverlappingElvis Avatar answered Sep 24 '22 16:09

OverlappingElvis