That's because categoryData is not an Array - it's an Object. And while some JS objects (arguments, for example) support length property, those created with object literal notation do not.
You can count your object's length by yourself, with this:
function countProps(obj) {
var count = 0;
for (var p in obj) {
obj.hasOwnProperty(p) && count++;
}
return count;
}
This can be done even in a more simple way, if your target environment supports (or has it shimmed) the Object.keys method:
function sizeObj(obj) {
return Object.keys(obj).length;
}
... and that's exactly how it's done in Underscore.js library method:
_.size = function(obj) {
if (obj == null) return 0;
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
};
Answer from raina77ow on Stack OverflowJavascript Array length not working in safari
Arr.length not working correctly
.length not working
node.js - Array length is not correct in javascript - 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));
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
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.
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);
}
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.
Its not an array you need to parse it first to get as an array :
var ownAc=JSON.parse(user.ownAccount)
console.log(ownAc.length);
Use the simple method Object.keys(obj) with the reference of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
In your case the answer is Object.keys(user.ownAccount).length
var user = {
"username": "testuser update",
"email": "user001@mail.co.th",
"name": "user001",
"ownAccount": [{
"id": 2,
"name": "Demo Account2"
},
{
"id": 1,
"name": "Demo Account"
}
]
};
console.log(Object.keys(user.ownAccount).length);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Objects don't have a .length property.
A simple solution if you know you don't have to worry about hasOwnProperty checks, would be to do this:
Object.keys(data).length;
If you have to support IE 8 or lower, you'll have to use a loop, instead:
var length= 0;
for(var key in data) {
if(data.hasOwnProperty(key)){
length++;
}
}
One option is:
Object.keys(myObject).length
Sadly it not works under older IE versions (under 9).
If you need that compatibility, use the painful version:
var key, count = 0;
for(key in myObject) {
if(myObject.hasOwnProperty(key)) {
count++;
}
}
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 ifToString(ToUint32(P))is equal toPandToUint32(P)is not equal to 232−1.
Since Hello is not valid, according to the above definition, it is not considered as an array index but just as an ordinary property.
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
So, only if the property is a valid array index, the length property will be adjusted.
In your case, you have just created a new property Hello on the array object.
Note: Only the numerical properties will be used in all of the Array's prototype functions, like forEach, map, etc.
For example, the array shown in question, when used with forEach,
arr.forEach(function(currentItem, index) {
console.log(currentItem, index);
})
would print
Hello 0
There 1
123 2
456 3
{ show: [Function] } 4
even though the list of keys shows Hello.
console.log(Object.keys(arr));
// [ '0', '1', '2', '3', '4', 'Hello' ]
It is because, Array is derived from Object,
console.log(arr instanceof Object);
// true
and Hello is a valid key of the array object, but just not a valid array index. So, when you treat the array as an Object, Hello will be included in the keys, but the array specific functions will include only the numerical properties.
javascript length is calculated as 1+(highest numeric index element). so when you add arr['Hello'], you are only adding a string index which is not taken into account when calculating the array length.
This is the actual definition of the array length property as described in ECMAScript 5.1:
Every Array object has a length property whose value is always a nonnegative integer less than 232. 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.