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

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.

Related

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 the type of a number element in an array is evaluated to be a string in javascript [duplicate]

This question already has answers here:
javascript for loop counter coming out as string [duplicate]
(3 answers)
Closed 3 years ago.
For example
var a = [1, 2, 3];
for (var i in a) {
console.log(typeof i);
}
Output
string
string
string
I am a Python programmer, and I find it very unintuitive. Why is not an element evaluated to be a number instead?
You are looping over the keys of the object. Meaning the keys you are actually testing is "0", "1", "2".
You can see that here, if you also console the i. Also, if you console the value that is located at that index in the array, and test that, you will see that it is a number:
var a = [1, 2, 3];
for (var i in a) {
console.log(i, typeof i, a[i], typeof a[i]);
}
In ES5, a new feature was added to arrays that loops through their values (and indexes): Array#forEach:
var a = [1, 2, 3];
a.forEach(function(v) {
console.log(v, typeof v);
});
In ES2015+, for-of was added, which will loop through the values using a for-style loop:
// ES2015+ only!!
let a = [1, 2, 3];
for (let v of a) {
console.log(v, typeof v);
}
why the type of a number element in an array is evaluated to be a string in javascript
If you really mean the element, not the index, then the problem is that you're just looking at the type of the wrong thing. See KevBot's answer.
If you're asking why the indexes (0, 1, and 2) are strings rather than numbers, since array indexes are normally numbers, it's because standard arrays in JavaScript aren't really arrays at all, they're just objects with some special behavior:
An Array object is an exotic object that gives special treatment to array index property keys (see 6.1.7). 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 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; and whenever the value of the length property is changed, every own property whose name is an array index whose value is not smaller than the new length is 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.
Until ES2015, all object property names were strings. (Now they can be either strings or Symbols.) Array indexes are just property names that conform to a specific definition:
A String property name P is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232-1.
See also A myth of arrays (on my blog).

Blank Array Returned A Length of 5

I have been watching PluralSight's Rapid JavaScript Training by Mark Zamoyta and I came across this. He showed these two examples. I've been trying to wrap my head around it, but still could not understand.
How is it able to capture the length of the entries after the array was created using new Array() method, seeing that it returned a blank array []. If it's blank like this [], shouldn't it return -1?
var entries = [1,2,3,4,5];
entries.length
=> 5
entries
=> [ 1, 2, 3, 4, 5 ]
var entries = new Array(5);
entries.length
=> 5
entries
=> []
var myArray = new Array(5);
When you define an array by passing the constructor an integer like above, memory is allocated for 5 slots in the array. If you examine the array, you will find:
console.log(myArray[1]);
=> undefined
console.log(myArray.toString);
=> ,,,,
As you can see, there are indeed five elements in the array, each of them undefined. So your array isn't "blank."
It is probably bad practice to initialize an array in this manner, as there just isn't a good use case for it. Pushing to the array will yield:
myArray.push("value");
console.log(myArray.toString);
=> ,,,,,value
...which is never what you want. I would advise initializing the array like below and forget that passing an integer to the constructor is even an option:
var myArray = [];
The length property of an array in JS is not calculated on the fly - it can also be set manually via the constructor or an assignment, and it's updated as objects are added or removed (Spec):
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[.]
It's a plain property that's kept up-to-date, not a calculation. Using the constructor new Array(5) initializes an array with length set to 5. You can also set it manually, which fills in undefined or truncates the array as needed:
var arr = [];
arr.length = 3;
// arr is now [undefined, undefined, undefined]

Why doesn't the length of the array change when I add a new property?

var arr = ["Hello", "There", 123, 456, {
show: function (value) {
alert(value);
}
}];
arr[4].show(arr[0]);
arr["Hello"] = {
damn: function () {
alert("What's happening yo !");
}
}
arr.Hello.damn();
alert("Arr length is: " + arr.length);
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 if ToString(ToUint32(P)) is equal to P and ToUint32(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.
This happens because length is only updated when a new numeric property is added to the array as required by the specification:
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.
And an array index is specified to be:
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.
However, arrays are also objects - so you can add non-array-index properties to an array, just like you can add properties to any other JavaScript object (which is why your example doesn't throw either).
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.
When you write:
arr["Hello"]=...
you are creating a new Object associated with the arr Array object, which does not affect the length of arr.
You can achieve the same effect by writing:
arr.Hello=...

Javascript array length incorrect on array of objects

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.

Categories