Javascript - array index issue in non sparse array - javascript

non sparse array are contiguous in nature and from 0 to length-1, all index should return true for 'in' operator. It should be true also for empty element.
obj1 = {x:1,y:2};
obj2 = Object.create(obj1);
obj2.z = 5;
var arr = [obj1,obj2,1,,2];
console.log(arr.length); //5
console.log(3 in arr);//false
index 3 is valid.
Why is it returning false?
Note: I am using latest firefox.
It should return false only for sparse array which doesn't have a specified index number 3.
Update: index 3 is valid so it should return true. in operator doesn't validate value of at the indexed position, it just validate the validity of index not the value

3 in arr is false because arr[3] is never set (and thus the array is indeed sparse).
Note the double comma in
var arr = [obj1,obj2,1,,2];
– if you make that
var arr = [obj1,obj2,1,2];
then 3 in arr becomes true.
See page 63 in the specification:
Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the
element list is not preceded by an AssignmentExpression (i.e., a comma at the beginning or after another
comma), the missing array element contributes to the length of the Array and increases the index of
subsequent elements. Elided array elements are not defined. If an element is elided at the end of an array,
that element does not contribute to the length of the Array.
– in other words, the behavior of your code is identical to
var arr = [obj1, obj2, 1];
arr[4] = 2;

Javascript is evaluating the value which is undefined. Undefined is falsy.
Array always have 0 based index, in your array 4th element (3 by index) is not set to any value.
Refere this
From the link
Here is what is falsy in JavaScript:
false
null
undefined
The empty string
''
The number 0 The number NaN (yep, 'Not a Number' is a number, it is a special number)
Everything else is truthy, and that includes Infinity (which is
another special number, like NaN), and all Object objects and Array
objects, empty or not.

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.

JavaScript negative element in array

This is my JavaScript array code for negative index number.
In output why doesn't consider negative index number in the count of the element? It shows only count (3) in output.
Code
let abc = ['gnagar', 'ahmedabad', 25];
console.log(abc, typeof(abc));
console.log(abc[-1]);
abc[-1] = 'abc';
console.log(abc, typeof(abc));
console.log(abc[-1]);
-1 is not a valid index for array.
The assignment abc[-1] = 'abc'; means set attribute "-1" to the abc object.
This is because array is type of object as you can see there typeof(abc) is object.
You can assign values in objects using [].
Negative indexes are not actual index so it does not impact the array length.

Generating a filled array in javascript [duplicate]

This question already has answers here:
Undefined values in Array(len) initializer
(5 answers)
Closed 7 years ago.
I would expect the following code to return [1,1,1,1...]
(new Array(10)).map(function() { return 1;})
but it returns [, , , , , ...].
Moreover,
(new Array(10)).length == 10 and (new Array(10))[0] == undefined are true.
And for z = function(){return 0;}; the expression z(undefined) === 0 is also true.
Yet I have noticed that [,,,,,,,,,,].map(function() { return 1; }) also returns [,,,,....].
Can anyone explain why?
So. I would expect the following code to return [1,1,1,1...].
(new Array(10)).map(function() { return 1;})
But it returns [, , , , , ...].
Right, because new Array(10) creates an array with no elements with a length of 10, and map only iterates over elements that actually exist. (And yes, this is surprising. :-) )
Moreover, (new Array(10)).length == 10 and (new Array(10))[0] == undefined are true.
Again correct, because (again) new Array(10) doesn't put any elements in the array, so accessing [0] gives you undefined.
JavaScript's standard arrays aren't really arrays at all, and they can have a length that's a positive number without having any entries in them. They're a form of "sparse" array.
Let's take a simpler example:
var a = new Array(10);
a[2] = 1;
That array contains one element, the element at index 2. There is no element at index 0, no element at index 1, and no elements at indexes 3 and above. It just has gaps there. You can tell by asking it:
console.log(0 in a); // "false"
console.log(1 in a); // "false"
console.log(2 in a); // "true"
Standard arrays in JavaScript are just objects with special behavior assigned to length, special behavior assigned to a class of property names (loosely, numeric ones), and that are backed by Array.prototype.
This is all in contrast to the newer "typed" arrays, Int32Array and such, which are true arrays in the traditional sense.
This will work:
Array.apply(null, Array(10)).map(…
Live demo: http://jsfiddle.net/xXG5p/
You have to make the array dense first. new Array(n) creates a sparse array. Sparse arrays do have a length but they have no elements. Hence, a .map() call will not iterate at all.
Using my code above, you will create a dense array that does contain elements (whose values are initially set to null).
Here is what the Mozilla Developer Network says about Array.prototype.map:
callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
When you call new Array(10), the Array you create believes it is 10-element long but none of its indexes have ever been assigned to. Here's an example of what happens if you use a literal array for which you have not set values for some indices:
[1, , 3].map(function () {return "a"})
The value you get is:
[ 'a', , 'a' ]
Because at index 1, no value was assigned.

Why does delete keep Array elements?

Today I stumbled upon a question here on Stack Overflow - How do I remove objects from a javascript associative array?. What struck me was that the accepted answer was both misleading and heavily upvoted, so I highlighted the possible pitfall.
However, while cobbling together a corrective answer, I realized I have no idea as to why it makes sense for delete to keep elements assign undefined instead of removal.
var elements = new Array()
elements.push(NaN)
elements.push(NaN)
elements.push(NaN)
delete elements[1]
console.log("number of elements: ", elements.length) // returns 3
Is there a rationale behind it?
I realized I have no idea as to why it makes sense for delete to assign undefined instead of removal.
It doesn't. delete removes properties from objects, it does not set them to undefined. Here's an easy way to tell:
var a = ['a', 'b', 'c'];
console.log(1 in a); // logs "true"
delete a[1];
console.log(1 in a); // logs "false"
Note that after the delete, a doesn't have a property called 1 anymore. At all.
Contrast with:
var a = ['a', 'b', 'c'];
console.log(1 in a); // logs "true"
a[1] = undefined;
console.log(1 in a); // logs "true"
There, a still has a property called 1, it's just that the property's value is undefined.
It's useful to understand that in JavaScript, arrays aren't really arrays at all. They're just objects, array "indexes" are just property names (which are strings — yes, really, we just tend to write them as numbers), arrays have special handling of property names that are all numeric (indexes), a special length property, and some functions they get from Array.prototype. This is very clearly laid out in Section 15.4 of the spec. Once you have it set firmly in your head that JavaScript arrays aren't really arrays, they make a lot more sense. :-)
Deleting an array "index" property from an array does not change its length (not even if you delete the highest-numbered one); it just creates a hole in the array (JavaScript "arrays" are sparse arrays by their nature; e.g., they can have gaps in them). So in my first example above, I get exactly the same array that I'd've gotten if I'd done this:
var a = [];
a[0] = 'a';
a[2] = 'c';
Note the gap, the array has no 1 element/property.
If you say:
var foo = a[3];
...foo can get the value undefined for two completely different reasons:
a has a property called 3 that has the value undefined, or:
a has no property called 3 at all; the result of a property accessor operation on an object that doesn't have a property by that name is undefined. This if-no-property-return-undefined is covered by the spec in a fairly convoluted way, but mostly in Section 8.12.3.
These are very distinct things.
It doesn't assign undefined. It deletes the property. (If you try to access a property that doesn't exist, you will get undefined, and length is based on the highest numbered item in the array).
It makes sense, because it works that way on any kind of object. For it to act otherwise, it would have to special case objects if they were an instanceof Array but only if it was a property with a numeric name.
Use splice if you want to remove an item from an array.
> var elements = [NaN, NaN, NaN];
> elements.splice(1,1);
> console.log(elements);
[ NaN, NaN ]
JavaScript arrays can be "sparse". That is, some slots can be empty in the sense of never having had a value assigned, or having a value deleted. If you test the value associated with that index you'll get back undefined because it doesn't exist, not because it was assigned the value undefined.
When delete removes an item from an array it doesn't automatically slide the rest of the elements up to fill the space: the other elements retain their existing indexes, which in turn means the .length property doesn't change since .length is defined as being equal to the highest assigned index plus one.
If you want to remove an array element and have the other elements renumbered use the .splice() method.
This is because delete operator removes property, and removed property has value undefined. To remove element from array you can use splice method of array.
All of this is because of how the delete operator in javascript work.
When you do not set property of object and try to check its value it will be undefined:
var obj = {};
alert(obj.foo); // undefined
which is the same as:
alert(obj['foo']); // undefined
And look at this:
// create empty object
var obj = {};
// check its property named 1
alert(obj[1]); // undefined
// set property named 1 to value 'fooo'
obj[1] = 'fooo';
// and check it
alert(obj[1]); // 'fooo'
// now delete it
delete obj[1];
// and check again
alert(obj[1]); // undefined
delete has removed property and its value is undefined - and all above code was about object.
Now look at the arrays:
var arr = []; // it's better to use [] than new Array();
alert(arr[1]); // undefined - same as above
// assign value
arr[1] = 'fooo'
// check it
alert(arr[1]); // 'fooo' - same as above
// remove it
delete arr[0];
// and check
alert(arr[1]); // undefined - same as above
So behavior is the same, but what about length property of array. Specification http://es5.github.com/#x15.4.5.2 says:
"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."
So when you look at this:
var arr = ['foo', 'bar', 'foobar'];
alert(arr.length); // 3
// delete first
delete arr[1];
// and check length
alert(arr.length); // 3
Last check gives 3 because the last deletable property in this array has index 2 - first property (with index 0) has value undefined (delete operator set this value), second item (with index 1) has value 'bar' and third (with index 2) has value 'foobar'. So according to specification length = 2 + 1 ('allways numerically greater than last deletable');
This is visible also in this code:
var arr = [];
arr[10] = 'foo';
// element with index 10 is set to 'foo' but elements from 0 to 9 don't have value - they are undefined
// now check length
alert(arr.lenght); // 11
Last deletable property index is 10, so 10 + 1 gives 11, despite of previous elements that are undefined.
So delete operator does his work, but it is not designed to remove items from array.

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