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++;
}
}
Answer from Cerbrus on Stack OverflowObjects 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++;
}
}
javascript - Array length and undefined indexes - Stack Overflow
javascript - Why array[array.length] returns undefined? - Stack Overflow
javascript - Array length undefined - Stack Overflow
javascript says array.length is undefined, but not the array - Stack Overflow
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
lengthproperty 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 ifToString(ToUint32(P))is equal toPandToUint32(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
undefinedelements in Arrays
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.
Arrays are zero-based indexing. Which means The first element of the array is indexed by subscript of 0 and last element will be length - 1
const arr = [2 , 3, 6, 8];
const end = arr[ arr.length - 1 ];
console.log(end);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
JavaScript array indexes start counting at 0. So...
arr[0] evaluates to 2
arr[1] evaluates to 3
arr[2] evaluates to 6
arr[3] evaluates to 8
arr.length evaluates to 4 because there are 4 elements in your array
arr[4] refers to the 5th element in an array, which in your example, is undefined
The reason is that you're not logging superArray in your fetch promise. If you add the call to console.log() in your last then() call it works. The reason for this is that fetch is executed asynchronously, which means that any additional code that comes after the fetch call is executed long before the fetch has returned anything.
The reason you can see a full log of superArray even when doing it outside the fetch is a special console behaviour.
const URL1 = "https://www.politifact.com/api/statements/truth-o-meter/people/barack-obama/json/?n=50";
const URL2 = "https://www.politifact.com/api/statements/truth-o-meter/people/hillary-clinton/json/?n=210";
const URL3 = "https://www.politifact.com/api/statements/truth-o-meter/people/bernie-s/json/?n=70";
var superArray = [];
fetch("https://cors-anywhere.herokuapp.com/" + URL1)
.then(results => {
return results.json();
})
.then(data => {
data = data.filter(function(item) {
return item.speaker.name_slug == "barack-obama" && item.statement_type.statement_type !== "Flip";
});
for (var i = 0; i < 10; i++) {
superArray.push(data.splice(Math.random() * data.length, 1)[0]);
}
})
fetch("https://cors-anywhere.herokuapp.com/" + URL2)
.then(results => {
return results.json();
})
.then(data => {
data = data.filter(function(item) {
return item.speaker.name_slug == "hillary-clinton" && item.statement_type.statement_type !== "Flip";
});
for (var i = 0; i < 10; i++) {
superArray.push(data.splice(Math.random() * data.length, 1)[0]);
}
})
fetch("https://cors-anywhere.herokuapp.com/" + URL3)
.then(results => {
return results.json();
})
.then(data => {
data = data.filter(function(item) {
return item.speaker.name_slug == "bernie-s" && item.statement_type.statement_type !== "Flip";
});
for (var i = 0; i < 10; i++) {
superArray.push(data.splice(Math.random() * data.length, 1)[0]);
}
console.log(superArray[0]);
})
It's possible to be logged into your console before data is fetched. To make it sure, log that after accomplishing the data ie. inside .then().
fetch(...)
.then(results => {...})
.then(data => {...})
.then(()=> console.log(superArr[0]))
Or, you may use:
superArray.length && console.log(superArray[0]);
Arrays can grow and shrink dynamically. So from a certain point of view, they are already of undefined length. You can always add new objects to it if you want to.
You can also create a helper function which checks first if an object exists at a certain position and if not, creates a new one.
You mentioned array[2].value = 'foo' as an example. Here is a helper function that you could use:
function getObjectAtIndex(arr, index) {
return arr[index] || (arr[index] = {});
}
and then, instead of writing array[2].value = 'foo', you'd write:
getObjectAtIndex(array, 2).value = 'foo'
In your array, pushing object in any way is right. That's totally ok. like:
var arr = [];
arr.push({}); // ok
aa[1] = {} // also ok
or:
var arr = [{}, {}, {}]; // the way you are doing is also fine
Or, if you want to do it via loop, that is also fine. Like:
var arr = [];
for(var i=0; i<5; i++){
arr[i] = {};
}