That's because length gives you the next index available in the array.
DOCS
arrayLength
If the only argument passed to the Array constructor is an integer between 0 and 2^32-1 (inclusive), this returns a new JavaScript array with length set to that number.
ECMA Specifications
Because you don't have inserted any element in the other keys than 21, 90, 13, all the remaining indexes contains undefined. DEMO
To get actual number of elements in the array:
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
var len = 0;
for (var i = 0; i < a.length; i++) {
if (a[i] !== undefined) {
len++;
}
}
document.write(len);
Shorter version
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
for (var i = 0, len = 0; i < a.length; i++, a[i] !== undefined && len++);
document.write(len);
DEMO
EDIT
If the array contains large number of elements, looping to get its length is not the best choice.
As you've mentioned in the question, Object.keys(arr).length is the best solution in this case, considering that you don't have any properties added on that array. Otherwise, the length will not be what you might be expecting.(Thanks To @RobG)
That's because length gives you the next index available in the array.
DOCS
arrayLength
If the only argument passed to the Array constructor is an integer between 0 and 2^32-1 (inclusive), this returns a new JavaScript array with length set to that number.
ECMA Specifications
Because you don't have inserted any element in the other keys than 21, 90, 13, all the remaining indexes contains undefined. DEMO
To get actual number of elements in the array:
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
var len = 0;
for (var i = 0; i < a.length; i++) {
if (a[i] !== undefined) {
len++;
}
}
document.write(len);
Shorter version
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
for (var i = 0, len = 0; i < a.length; i++, a[i] !== undefined && len++);
document.write(len);
DEMO
EDIT
If the array contains large number of elements, looping to get its length is not the best choice.
As you've mentioned in the question, Object.keys(arr).length is the best solution in this case, considering that you don't have any properties added on that array. Otherwise, the length will not be what you might be expecting.(Thanks To @RobG)
The array in JavaScript is a simple zero-based structure. The array.length returns the n + 1 where n is the maximum index in an array.
That's just how it works - when you assign 90'th element and this array's length is less than 90, it expands an array to 90 and sets the 90-th element's value. All missing values are interpreted as null.
If you try the following code:
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
console.log(JSON.stringify(a));
You will get the following JSON:
[null,null,null,null,null,null,null,null,null,null,null,null,null,{},null,null,null,null,null,null,null,{},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{}]
Moreover, array.length is not a readonly value.
If you set a length value less than the current, then the array will be resized:
var arr = [1,2,3,4,5];
arr.length = 3;
console.log(JSON.stringify(arr));
// [1,2,3]
If you set a length value more than the current, then the array will be expanded as well:
var arr = [1,2,3];
arr.length = 5;
console.log(JSON.stringify(arr));
// [1,2,3,null,null]
In case you need to assign such values, you can use JS objects.
You can use them as associative array and assign any key-value pairs.
var a = {};
a[21] = 'a';
a[90] = 'b';
a[13] = 'c';
a['stringkey'] = 'd';
a.stringparam = 'e'; // btw, a['stringkey'] and a.stringkey is the same
console.log(JSON.stringify(a));
// returns {"13":"c","21":"a","90":"b","stringkey":"d","stringparam":"e"}
console.log(Object.keys(a).length);
// returns 5
node.js - Array length is not correct in javascript - Stack Overflow
Javascript array length incorrect on array of objects - Stack Overflow
javascript - Array length incorrect - Stack Overflow
JavaScript array length issue - Stack Overflow
.length is a special property in Javascript arrays, which is defined as "the biggest numeric index in the array plus one" (or 2^32-1, whatever comes first). It's not "the number of elements", as the name might suggest.
When you iterate an array, either directly with for..of or map, or indirectly with e.g. JSON.stringify, JS just loops over all numbers from 0 to length - 1, and, if there's a property under this number, outputs/returns it. It doesn't look into other properties.
The length property don't work as one will expect on arrays that are hashtables or associative arrays. This property only works as one will expect on numeric indexed arrays (and normalized, i.e, without holes). But there exists a way for get the length of an associative array, first you have to get the list of keys from the associative array using Object.keys(arr) and then you can use the length property over this list (that is a normalized indexed array). Like on the next example:
arr=[];
arr[0]={"zero": "apple"};
arr[1]={"one": "orange"};
arr["fancy"]="what?";
console.log(Object.keys(arr).length);
And about this next question:
not able to get all values while doing console.log(JSON.stringify(arr))
Your arr element don't have the correct format to be a JSON. If you want it to be a JSON check the syntax on the next example:
jsonObj = {};
jsonObj[0] = {"zero": "apple"};
jsonObj[1] = {"one": "orange"};
jsonObj["fancy"] = "what?";
console.log(Object.keys(jsonObj).length);
console.log(JSON.stringify(jsonObj));
One thing to note is that there is a difference between regular arrays and associative arrays. In regular arrays (real arrays), the index has to be an integer. On the other hand, associative arrays can use strings as an index. You can think of associative arrays as a map if you like. Now, also note, true arrays always start from zero. Thus in your example, you created an array in the following manner:
a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"}
Javascript was able to convert your string indexes into numbers, hence, your code above becomes:
a = [];
a[1] = {"blah"};
a[2] = {"blah"};
But remember what i said earlier: True arrays start from zero. Therefore, the javascript interpreter automatically assigned a[0] to the undefined. Try it out in either firebug or the chrome/safari console, and you will see something like this when you try to print "a". You should get something like "[undefined, Object, Object]. Hence the size 3 not 2 as you expected.
In your second example, i am pretty sure you are trying to simulate the use of an associated array, which essentially is adding properties to an object. Remember associated arrays enable you to use strings as a key. So in other terms, you are adding a property to the object. So in your example:
b["key1"] = {"string1":"string","string2":"string"};
this really means:
b.key1 = {"string1":"string","string2":"string"};
Initializing b =[] simply creates an array, but your assignment doesn't populate the array. It simply gives "b" extra properties.
length returns 1 + the largest integer key in the object.
In a the largest key is 2 so 1+2 is 3.
In b there are no integer keys (the keys there are key1 and key2 which cannot be converted into ints) so Javascript assumes that the largest key is -1, and 1 + -1 yields 0.
This program will help you see that:
a = [];
a["1"] = {};
a["4"] = {};
alert(a.length); // Prints 5
The second log message cannot output the length of the array because the values have been assigned to its properties as opposed to its indices, since there are no objects within the actual indices of the array the length property is 0. This occurs because arrays cannot contain non-numeric indices such as A,B,C,D.
So when you execute:
var arr= [];
arr["b"] = "test";
The code is actually assigning the string literal test to the b property of the arr array as opposed to an index. This is possible because arrays are objects in Javascript, so they may also have properties.
The length of an Array object is simply its highest numeric index plus one. The second object has no numeric indices, so its length is 0.
If it were [ A: Object, B: Object, C: Object, 15: Object ], then its length would be 16. The value of length is not tied to the number of actual properties (4 in this case).
The .length is defined to be one greater than the value of the largest numeric index. (It's not just "numeric"; it's 32-bit integer values, but basically numbered properties.)
Conversely, setting the .length property to some numeric value (say, 6 in your example) has the effect of deleting properties whose property name is a number greater than or equal to the value you set it to.
The effect of
var c = [];
c[10] = "foo";
is that c will look like this:
c[0] === undefined
c[1] === undefined
c[2] === undefined
c[3] === undefined
c[4] === undefined
c[5] === undefined
c[6] === undefined
c[7] === undefined
c[8] === undefined
c[9] === undefined
c[10] === "foo"
Having elements 0 through 10, the length of the array is therefore 11.
I'll convert my original comment to a more thorough answer.
Array indexes that are counted in .length go from 0 and up. Negative indexes are considered properties of the object, not array values. As you can see from the ECMAScript spec below, array indexes are essentially just certain types of property values given some special treatment.
From section 15.4 of the ECMAScript spec:
15.4 Array Objects
Array objects give special treatment to a certain class of property names. 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 2^32. A property whose property name is an array index is also called an element. Every Array object has a length property whose value is always a nonnegative integer less than 2^32 . The value of the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, 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. This constraint applies only to own properties of an Array object and is unaffected by length or array index properties that may be inherited from its prototypes.
Also, you should never "iterate" arrays with a for-in-loop:
for (var i in a1)
That iterates all enumerable properties of a1 which will include all array indexes, but could also include other properties. If you want to iterate only array elements with a for loop, you should use the other form:
for (var i = 0, len = a1.length; i < len; i++)
It is slightly more typing, but a lot safer.
Or, in more modern browsers, you can use the .forEach() method.
It is because arrays in Javascript are zero-based, i.e. they start from zero and go up to length - 1.
You usually write your for loops to be bound by less-than operator like this:
for(i = 0; i < arr.length; i++) {
// do something with arr[i]
}
this.Hats[ "Red" ] = new Hat( oPar, "red" )
this.Hats[ "Yellow" ] = new Hat( oPar, "yellow" );
This is where your problem is. You aren't using the array as an array, you're just using it as an object, setting the properties Hats.Red and Hats.Yellow instead of filling the array indexes.
Try this:
this.Hats.push( new Hat( oPar, "red" ) );
this.Hats.push( new Hat( oPar, "yellow" ) );
The push function in javascript
You're using an associative array. This type of array allows you to define a key for each array member. Using an array this way means that there is no index value upon which you can traverse the members, instead you can use for (var i in object).
for (var key in test.People["Fred"].Hats) {
console.log(key);
}
As stated here the length of an array must be less than 2 to the power of 32.
Your timestamps are larger than 2 to the power of 32, so cannot be array indices.
If you create an array a = [] and assign to a particular index a[33] = 'hi' then the previous 33 values will be undefined. But if the index you assign to is greater than 2**32 then the previous values will not be created, so the length of your array will be 0.
If you use a value over 2**32 as an index it will be treated as a property instead. So, if you want you can try iterating over the properties of the array.
I suggest that instead of combinedArray[value[0]], which will create properties, the following will get you an array you can iterate over:
var combinedArray = [];
var timestampIndices = [];
$.each(data.new, function(key, value) {
combinedArray.push([value[0], value[1]]);
timestampIndices.push(value[0]);
});
$.each(data.repeat, function(key, value) {
let index = timestampIndices.indexOf(value[0]);
combinedArray[index].push(value[1]);
});
The indices of your array are outside of the valid range of a positive 32 bit interger value.
From Array#length:
The
lengthproperty of an object which is an instance of typeArraysets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.
var array = [];
array[1541030400000] = 'foo';
console.log(array.length);
console.log(array);
console.log(array[1541030400000]);
To overcome this problem, you could take timestamps without milli seconds and take a smaller value as index for the array.
The array is then iterable with standard methods.
The answer is that my_array.length does work but you're missing some of the implicit type conversions that are happening and what push() does.
In the first example, you are creating a multidimensional array. Technically it's an array of arrays rather than a true multidimensional array. The first code snippet creates this array of arrays:
[
["name", "url"],
["dog", "cat"]
]
which is of length 2 so that result is correct.
The second example's use of the concatenation operator + converts spamfoo to a string, which means that length is now returning the string length. The string length is 15 so this too is correct.
You might want to add this line to your examples:
alert(typeof spamfoo);
If so you'll see the first example displays object and the second displays string.
For the first part, you'll get a nested array (2x2), hence spamfoo.length returns 2. It looks like:
[
['name', 'url'],
['dog', 'cat']
]
The second part, is as cletus said above, is a type casting into string
Your notation seems odd. The square brackets are for an array, but the contents are object attribute/value notation. I don't think that will work. You can turn your expression into an object by replacing the [] with {}, but then, objects don't have length. You can get the number of keys in an object with:
Object.keys(obj).length
Alternatively, you can iterate through the object keys with:
for (var key in obj) {
. . .
}
EDIT For the specific code you added, you can replace this line:
console.log(errors.length);
with:
console.log(Object.keys(errors).length);
In JavaScript, assotiative-array-like structure is Object:
{
lorem: 'ipsum',
dolor: 'amet'
}
In your example, replace square brackets with curly brackets, and you'll get such object.

