Unable to set array index at 0th position in JavaScript - javascript

Here is a simple js code :
let day = 10;
let arrayMinutes = Array(day);
const d = new Date();
d.setHours(0);
d.setMinutes(1);
d.setSeconds(0);
arrayMinutes[0] = d;
console.log("arrayMinutes[0]", d, arrayMinutes[0], arrayMinutes);
const d2 = new Date();
d2.setHours(0);
d2.setMinutes(day);
d2.setSeconds(0);
arrayMinutes[day - 1] = d2;
console.log("arrayMinutes[day]", arrayMinutes[0], arrayMinutes[day - 1], arrayMinutes);
And the console logs :
Why arrayMinutes[0] evaluates to 0?
According to me it should be equal to d.

The Array() constructor can be used in two ways:
Array(el0, el1, el2, ...)
Creates an array containing el0, el1, el2, .... This is equivalent to [el0, el1, el2, ...]
Array(count)
Creates an array with count elements, but the elements are uninitialized
If there's a single argument and it's an integer, it's taken to be the second form. So if day is an integer, you're creating an uninitialized array containing day elements.
Don't use Array(day), use [day] to create an array just containing the value day.

Beware using the Array constructor. My guess is that your day variable at the beginning of the code is a number. When you do Array(number), it creates an array with no entries in it and a length matching that number:
const a = Array(10);
console.log(a.length); // 10
console.log(a[0]); // undefined
console.log(0 in a); // false
In fact, doing that is almost the only time the Array constructor is useful. Any other time, use an array literal:
const a = [10];
console.log(a.length); // 1
console.log(a[0]); // 10
console.log(0 in a); // true
The reason I say "beware" is that Array behaves differently based on what you give it:
If you give it a single number argument, as above, it creates an empty array with length set to that number.
If you give it a single non-number argument, it creates an array containing that value (with length = 1).
If you give it more than one argument, it creates an array containing those values (even if the first one is a number).
This...changing...behavior is why you should avoid the Array constructor entirely unless you're intentionally creating an empty array of a specified length (usually just prior to filling it).

Maybe try with push
arrayMinutes.push(d);

Related

Convert a number (i. e. 5) to length of an array

I want to create a property on a polymer custom element that let's the user define a number of elements to repeat.
<my-element repeated-elements='5'></my-element>
This should tell my element to repeat the element inside of the component five times. For that I need an array with length of 5, so anything like this would do:
['','','','','']
Is there a way to do this in JavaScript? The number would be passed as a number, not a string. So somehow I would need to convert any number to the amount of array items in an array. Metaphorically speaking:
convertToArrayLength(5);
I'm completely lost here, I have no idea at all how this could be done.
The array constructor does exactly that:
var arr = Array(5);
console.log(arr, arr.length);
//=> Array [ <5 empty slots> ] 5
You don't need to put new before calling Array (just a peculiarity of the API).
Note though that arrays in JavaScript are dynamic, so most of the time you don't need to specify the length of your array beforehand and can simply initialize your variable with:
var arr = [];
// And then push to it as you go:
arr.push(x);
JavaScript will re size the array automatically as you push to it.
var array = new Array(5); // undefined
array.length; // 5
array.push("FOO"); // 6
array.length; // 6
All you have to do is make sure you assign the variable as an Array with either [] or new Array

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.

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"

Is Array(5) equivalent to var a = []; a.length = 5; in JS?

I see four five options to initialize an array to a specific length in JS, (the last one is a stretch, I know):
var a = []; a.length = 5;
var a = Array(5);
var a = []; a[4] = undefined;
var a = new Array(5);
function makeArrayToLength(length, default){
var a = [], i = 0;
for(; i < length; i++){
a[i] = default;
}
return a;
}
I definitely want to (and do) use the literal whenever possible, but I'm in a situation where the defining aspect of a particular array is its length, so I'm leaning towards Array(5). Is the first example equivalent to the second in terms of end result? I realize it's not equivalent in the execution.
The first two, and the third examples are equivalent, at the end they produce an Array object with only one own property, length, containing 5 as its value.
When you call the Array constructor using a single numeric argument (like Array(5);), the newly created object will contain that number as its length property, the index properties aren't created:
var a = Array(5);
a.hasOwnProperty('0'); // false
The second example produces just the same:
var a = [];
a.length = 5;
a.hasOwnProperty('0'); // false
About the third example, it isn't equivalent because it will create a property on the array object, even though its value is undefined:
var a = []; a[4] = undefined;
a.hasOwnProperty('4'); // true
The fourth example:
var a = new Array(5);
Is just exactly the same as the second one (var a = Array(5);), there's no difference between using the Array constructor with or without the new operator, in the second example you are calling the Array constructor as a function.
And finally, about your makeArrayToLength function, by now I think you know isn't equivalent at all, since all the "index properties" are initialized to a "default" value. (BTW don't use default as Identifier, it's a Keyword...)
The Array constructor is usually avoided because it can have different behaviors depending the argument used, for example:
Array("5"); // one element array, (["5"])
Array(5); // empty array, length = 5
// v.s.
["5"] // one element array
[5] // one element array
Also, the Array constructor could be overriden, while array literals will always work.
Yes, they all produce the same result.
2 and 4 are the same because, according to the ECMAScript spec:
15.4.1 The Array Constructor Called as a Function When Array is called as a
function rather than as a constructor,
it creates and initialises a new Array
object. Thus the function call
Array(...) is equivalent to the object
creation expression new Array(...)
with the same arguments.
1 and 2 are equivalent because [] constructs a new array and setting the length property is equivalent to constructing an Array with new Array(length) (in the spec).
Option 3 is also equivalent because:
...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 option 5 is basically just option 3, but repeated multiple times up to the maximum index.

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