JavaScript new Array(n) and Array.prototype.map weirdness
It appears that the first example
x = new Array(3);
Creates an array with a length of 3 but without any elements, so the indices [0], [1] and [2] is not created.
And the second creates an array with the 3 undefined objects, in this case the indices/properties them self are created but the objects they refer to are undefined.
y = [undefined, undefined, undefined]
// The following is not equivalent to the above, it's the same as new Array(3)
y = [,,,];
As map runs on the list of indices/properties, not on the set length, so if no indices/properties is created, it will not run.
Why is Array.map returning different results?
Array(n)
creates an array of length n
, but the array has no values in it so there is nothing to map over.
Basically, this:
const a = Array(n);
is the same as:
const a = [];
a.length = n;
This is why the created array has no elements in it. Attempting to map it will do nothing since there are no values to map.
You can, however, convert that empty array to an array of undefined
values. This can be done in two ways:
One is using the spread operator as you have done:
[...Array(n)] // creates new array [undefined, undefined, undefined ...] n times
The other, more commonly used, is .fill()
, which sets its parameter as the value for all the indices of the array. To fill with undefined
, do:
Array(n).fill() // fills array with [undefined, undefined, undefined ...] n times
An array of undefined
, unlike an empty array, has elements and can therefore be mapped:
[undefined, undefined, undefined].map(x => 1) // [1, 1, 1]
So you can first convert your empty array to an array of undefined
, and then map it like so:
Array(n).fill().map(x => 1)
If you want to fill the array with the same element in each position like in this example, you can simply pass it in to fill without needing to map the array:
Array(n).fill(1)
How does `new Array(5).map()` work?
Array.apply(null, Array(5))
actually fills the array (or array-like object) that you pass as the second argument with the value of the first argument you pass in, as can be seen in the MDN Docs.
new Array(5)
is just initializing an array with it's length property set to the argument of 5
. Again, as can be seen in the MDN docs:
If the only argument passed to the
Array
constructor is an integer between 0 and 232-1 (inclusive), this returns a new JavaScript array with itslength
property set to that number (Note: this implies an array ofarrayLength
empty slots, not slots with actual undefined values).
Nested Array.prototype.map
In the end, I restructured the way the product options are added to the cart:
So when I check or uncheck boxes, my child component will pass the same option object like before:
let option = {
groupId: groupId,
groupName: groupName,
optionId: optionId,
optionName: optionName,
optionPrice: optionPrice,
}
The parent function receives the option object and builds the object structure to be appended to the add to cart item from the child component:
let object = {
groupId: option.groupId,
groupName: option.groupName,
groupOptions: [{
optionId: option.optionId,
optionName: option.optionName,
optionPrice: option.optionPrice
}]
};
Before doing that, it checks if the group already exists, if it does then it just appends the option object into groupOptions:
let currentOption = {
optionId: option.optionId,
optionName: option.optionName,
optionPrice: option.optionPrice
}
Now I just render it back out as a simple nested array.prototype.map and everything works good.
Map returns Empty statement array
you can do something like this
function getDaysArray(days) {
return Array.from({length: days}).map((_, i) => i + 1)
}
console.log(getDaysArray(31))
Unable to create and map through an array using new Array
You need to fill
the array before mapping, as map
ignores empty slots.
new Array(5).fill().map(num => <input />)
However, Array.from
would be more suitable in this case.
Array.from({length: 5}, ()=> <input />)
Array.map doesn't seem to work on uninitialized arrays
If you'd like to fill an array, you can use Array(5).fill()
and the methods will then work as expected--see the alternate related answer from aasha7. Older pre-fill approaches include:
Array.apply(null, new Array(5)).map(function() { return 0; });
// [ 0, 0, 0, 0, 0 ]
After some reading one of the posts linked in the comments, I found this can also be written as
Array.apply(null, {length: 5}).map(function() { return 0; });
However, trying to use .map
on undefined values will not work.
x = new Array(10);
x.map(function() { console.log("hello"); });
// so sad, no "hello"
// [ , , , , , , , , , ]
.map
will skip over undefined values :(
forEach is not a function error with JavaScript array
First option: invoke forEach indirectly
The parent.children
is an Array like object. Use the following solution:
const parent = this.el.parentElement;
Array.prototype.forEach.call(parent.children, child => {
console.log(child)
});
The parent.children
is NodeList
type, which is an Array like object because:
- It contains the
length
property, which indicates the number of nodes - Each node is a property value with numeric name, starting from 0:
{0: NodeObject, 1: NodeObject, length: 2, ...}
See more details in this article.
Second option: use the iterable protocol
parent.children
is an HTMLCollection
: which implements the iterable protocol. In an ES2015 environment, you can use the HTMLCollection
with any construction that accepts iterables.
Use HTMLCollection
with the spread operatator:
const parent = this.el.parentElement;
[...parent.children].forEach(child => {
console.log(child);
});
Or with the for..of
cycle (which is my preferred option):
const parent = this.el.parentElement;
for (const child of parent.children) {
console.log(child);
}
Related Topics
Facebook Js Sdk'S Fb.API('/Me') Method Doesn't Return the Fields I Expect in Graph API V2.4+
Uploading Both Data and Files in One Form Using Ajax
All Falsey Values in JavaScript
Formatting a Number With Exactly Two Decimals in JavaScript
How to Check If an Object Has a Specific Property in JavaScript
Can't Append ≪Script≫ Element
Negative Lookbehind Equivalent in JavaScript
Why Is Setstate in Reactjs Async Instead of Sync
Generate Random String/Characters in JavaScript
Format Number to Always Show 2 Decimal Places
How to Empty an Array in JavaScript
Listening For Variable Changes in JavaScript
How to Access React Instance (This) Inside Event Handler
How to Filter Object Array Based on Attributes
What Is Jsonp, and Why Was It Created
How to Create a File in Memory For User to Download, But Not Through Server
How to Check If Element Is Visible After Scrolling
Filter Array of Objects Based on Another Array in JavaScript