Javascript array length incorrect on array of objects - javascript

Could someone explain this (strange) behavior? Why is the length in the first example 3 and not 2, and most importantly, why is the length in the second example 0? As long as the keys are numerical, length works. When they are not, length is 0. How can I get the correct length from the second example? Thank you.
a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"};
alert(a.length); // returns 3
b = [];
b["key1"] = {"string1":"string","string2":"string"};
b["key2"] = {"string1":"string","string2":"string"};
alert(b.length); // returns 0

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

From the ECMAScript standard, ECMA-262, 5th ed.
15.4.5.2 length
The length property of this Array object is a data property whose value is always numerically greater than the name of every deletable property whose name is an array index.
Note the length property of an array only takes into account array indices, which are integers; setting other properties doesn't affect length.
For an array, a["3"] is equivalent to a[3] (this behavior is specified by ยง 15.4.5.1); 3 is an array index rather than a property. Thus setting a["3"] affects the array's length. b["key1"] is equivalent to b.key1. Setting properties don't affect the length of a collection.

Related

Javascript array of json prints empty but it has an object inside

I'm trying to understand why Javascript prints an empty array when it should have at least one value inside it. Please, check this code:
detail = [];
detail.cat1=[];
detail.cat2=[];
detail.cat3=[];
detail.cat4=[];
var newEntry = {"cod":"01","dt":"2021-10-02 09:07:21.205-07:00"};
detail.cat2.push(newEntry);
console.log(detail);
console.log(detail.length);
console.log(detail.cat2);
The results are:
> Array []
> 0
> Array [Object { cod: "01", dt: "2021-10-02 09:07:21.205-07:00" }]
How could it print [] since I have one object inside? And how can the length be zero? I was using any Javascript online editor, and the result is the same.
Since an array is really an object, we can add methods/properties directly to an individual array.
Then if you want to see the keys in an object for instance, Object.keys won't see it, but Reflect.ownKeys() will.
The Reflect version of defineProperty will return success or fail, while Object's returns the object passed.
Remember Reflect.preventExtensions() will (like it says) stop you or others from extending them.
As far as question about length is there, ".length" gives length of values not properties so it still gives 0
Array is an indexed collection of values, means you can put element at particular index and get element from particular index.
In the below example, you can see that if there are already elements in an array then you can get its length using length property.
Remember: The length of an array is (highest integer index at which the element is present in array + 1)
const arr = [1, 2, 3, 4];
console.log(arr); // prints whole array
console.log(arr.length); // prints length of an array
console.log(arr[2]); // Element at index 2
If you set element at particular index let say arr[8] = "something" then its length will be 9
const arr = [];
arr[8] = "something";
console.log(arr.length) // 9
It is true that array's are objects, so you can set/get values to/from array. But if you set property that is not a numbered index then it will not increase its length but It will set the property to that array object as:
const arr = [];
arr["introduction"] = "I'm an array";
arr.property = "This is a property"
console.log(arr.length);
console.log(arr.introduction);
console.log(arr.property);
When displaying an array, the default Array.prototype.toString method is usually called. This actually calls Array.prototype.join with no arguments, so produces a comma separated string of the elements of the array.
The join method only returns properties that have a positive integer name (an array index, indicating an array element), other properties are ignored by join.
Similarly, only elements of the array affect the length property, ordinarly properties (i.e. those that don't have an array index for their name) don't affect length.

Trying to get Array length

See below given scenario
var x = [];
x['abc'] = "hello";
console.log(x.length); //returns 0
var x = [1,2];
x['abc'] = "hello";
console.log(x.length); //returns 2
Any reason behind this or Am i missing anything?
As per spec
The value of the length property is numerically greater than the name
of every own property whose name is an array index; whenever an
own property of an Array object is created or changed, other
properties are adjusted as necessary to maintain this invariant.
Further
Specifically, whenever an own property is added whose name is an array
index, the value of the length property is changed.
So, length property is adjusted when the property whose name is an array index is created, only then length property changes.
'abc' being a non-numeric (and hence not an index of an array) when added to the array, doesn't reflect any change in length property.
By writing
var x = [ ];
you are defining a standard array where indexes can only be integers.
x['abc'] = "hello";
When you do x["abc"] since abc (which is what you use as index) is not an integer you are basically defining a property to the arr object (everything is object in javascript) but you are not adding an element to the standard array. and hence you array remains as it was.
var x = [];
x["abc"] = "hello";
console.log(x);
and that is the reason the size of the array is 0 in the first case and 2 in the second
When you wish to add property to x with string keys, you need to define you variable as an object.
var x = {}
x['abc'] = "hello";
and then you can get the size of you Object(which is indeed the number of keys in your object) by
Object.keys(x).length
you cannot access the array without the index. If you want to insert particular data in an array you can give it like,
var x = [];
x[0] = "hello";
alert(x.length) //will return 1
What you have done is that you have converted your array into an associative array, where your indices are the reference to the value assigned. This is similar to the objects concept in Javascript.
The length is 0 because a real array starts from index 0. So if you check for your array
console.log(x[0]) //undefined
hence, the length 0.
You cannot append a user defined key that isn't a number in JavaScript, as you can do in Python or Php etc. In JavaScript the key's of the Array shall only be numeric.
Thus doing:
var x = [];
x['abc'] = "hello";
console.log(x.length);
returns the length of x as 0. As nothing has been pushed into the array.If you do console.log(x), you'll find out that the array has no values or is empty.
Whereas doing this:
var x = [1, 2];
x['abc'] = "hello";
console.log(x.length); //returns 2
returns the length as 0 because the array consists of number 1 at the index 0 and the number 2 at the index/position 1 of that array. Just those values are there in the array, if you want to push "hello" push it like, x.push("hello") which will push it at the index 2 of the array.
If you still want to use alphabetic index use Objects instead.

Why javascript shows 0 length for array with object property instead of indexed element

For Example:
var arr = [];
arr[3.4] = 1;
console.log(arr.length);
In the above code sample the length property holds zero why and what happened inside JS parser because it's length is zero.
An array's length is reflective of the largest array index present in the array. An "array index" (see below) is a property name that is an integer value less than 232โˆ’1. Since 3.4 is not an integer, setting it does not alter the length.
Arrays are objects, so there is no reason why an array can't have a property named 3.4, but that property doesn't influence the length because its name does not fit the criteria of an array index.
ES2015 9.4.2, Array Exotic Objects defines an "array index" as an integer less than 232โˆ’1:
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 232โˆ’1."
And that definition is used in relation to the length value (emphasis mine):
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 own property whose name is an array index; whenever an own property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever an own property is added whose name is an array index, the value of the length property is changed, if necessary, to be one more than the numeric value of that array index...
A JavaScript array can not have fractional indexes.
What you have done there is assigned a property called "3.4" on the array object.
This does not affect the length property, which is designed to return one number higher than the highest valid index.
If you think about how arrays are supposed to work, you should realise a fractional offset doesn't make sense.
You could try using an object vs an array.
var arr = {};
arr[3.4] = 1;
arr[3.5] = 2;
arr[3.6] = 3;
console.log(Object.keys(arr).length);
You must use an integer as an index, not a float.
var arr = [];
arr[3] = 1;
console.log(arr.length);

Is an array in JS actually filled with empty spaces or when printed is it filled with zeros?

I have an array:
mydata =[];
i am storing values in the array by using a numeric key that can be somewhat big
mydata[13525] = 1;
However if i only store one item as the above, when i print the array in the console it prints 13524 commas before the object, nevertheless the debugger tells me it has length 13526 and there is only one element in the array.
I am confused as i understood that JS arrays do not required every position to be filled and certainly this might consume a lot of memory on bigger numbers. Can you explain please?
The .length property of an array represents the highest index plus one in the array that has been assigned a value.
When you do not assign intermediate values (and thus have a sparse array), the intervening values that you have not assigned are undefined which is essentially the "nothing here" value in Javascript. The console chooses to display arrays by trying to show you every value between 0 and the end of the array which is simply not a very good way to display a sparse array that is mostly empty. That's more an artifact of a design choice in the console than anything else. One could design a different way to display contents of an array that would handle sparse arrays differently.
Arrays are most efficient if you use consecutive indexes started from 0. That's what they are mostly designed for and what many implementations are optimized for since a runtime can do some optimized things if it knows there is a sequential set of values.
If you know you're going to mostly not be using sequences of numeric indexes starting from 0 and as such the .length property is of little use to you, then perhaps a plain object with arbitrary properties is a better choice.
var mydata = {};
mydata[13525] = 1;
console.log(mydata[13525]); // 1
console.log(mydata.length); // undefined - no .length property on an object
console.log(myData); // {1: 13525}
If you only want to print any non-null value in the array, instead of printing the whole array I'd use a for loop that only prints non-null values. It'd be something like this...
for (i = 0; i < mydata.length; i++) {
if(mydata[i]!= null){
console.log(mydata[i]);
}
}
javascript array is bit different from others,
var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]
foo.length = 6;
foo.push(4);
foo; // [1, 2, 3, undefined, undefined, undefined, 4]
While the getter of the length property simply returns the number of elements that are contained in the array, in setter, a smaller value truncates the array, larger value creates a sparse array. Guess what the setter mydata[13525] = 1; would do.
src: Javascript Garden
Edit:
to print/use only the values present, you can do
mydata.forEach(function(v){console.log(v);});

InArray returning -1 with matching value

var x = new Array(10);
$.inArray(10,x);
#Returns -1
Fiddle
I've come across this weird issue, checking a value in an array with $.inArray, really simple.
But, if the array only has one value in it, inArray returns -1.
If I add another value to the array, it works as expected.
This only happens with integers and not with strings.
What's going on?!
If you want to create an array with the one number(10) inside you should use bracket literal:
var x = [10];
$.inArray(10,x);
Or with push:
var x = new Array();
x.push(10);
Obviously the first one is more readable and faster to write.
A JavaScript array is initialized with the given elements, except in the case where a single argument is passed to the Array constructor and that argument is a number. Note that this special case only applies to JavaScript arrays created with the Array constructor, not with array literals created with the bracket syntax.
If the only argument passed to the Array constructor is an integer, a new, empty JavaScript array and its length is set to that number
MDN
Fixed fiddle
I suggest to check documentation for arrays in JavaScript, link: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
In your case, by using:
var x = new Array(10);
It creates an array with length 10 and each item of the array is undefined
I suggest to use:
var x = [10];
this is an array with one item at index 0 that has value 10.
var x = new Array(10); creates an array with 10 slots, not an array that contains "10"

Categories