Source content can be found here: https://github.com/LinkedInLearning/javascript-essential-training-2832077/tree/main/08_17. Code in question is this block right here:
import backpackObjectArray from "./components/data.js";
const content = backpackObjectArray.map((backpack)=>{
let backpackArticle = document.createElement("article");
backpackArticle.classList.add("backpack");
// Set article ID to the backpack.id property
backpackArticle.setAttribute("id", backpack.id);
backpackArticle.innerHTML=`
<figure class="backpack__image">
<img src=${backpack.image} alt="" />
</figure>
<h1 class="backpack__name">${backpack.name}</h1>
<ul class="backpack__features">
<li class="packprop backpack__volume">Volume:<span> ${
backpack.volume
}l</span></li>
<li class="packprop backpack__color">Color:<span> ${
backpack.color
}</span></li>
<li class="backpack__age">Age:<span> ${backpack.backpackAge()} days old</span></li>
<li class="packprop backpack__pockets">Number of pockets:<span> ${
backpack.pocketNum
}</span></li>
<li class="packprop backpack__strap">Left strap length:<span> ${
backpack.strapLength.left
} inches</span></li>
<li class="packprop backpack__strap">Right strap length:<span> ${
backpack.strapLength.right
} inches</span></li>
<li class="feature backpack__lid">Lid status:<span> ${
backpack.lidOpen ? "open" : "closed"
}</span></li>
</ul>
`;
return backpackArticle;
})
const main = document.querySelector(".maincontent");
content.forEach((backpack)=>{
main.append(backpack);
}
)
In essence, is it possible to just use forEach loop to output the same result as when we use map() array method, which is to output a HTML article for each object?
*Pseudo-code* Array.prototype.map(function(ea){return backpackArticle})
will simply create a new array and include whatever you return in each iteration.
You can achieve the same thing in other ways, but, as was already said, with more code. Really, the 'significance' in this case is simply achieving the intended result with less code.
I think in your example, it's to explicitly create a new array and then explicitly append each backpackArticle
to the <main>
using a forEach. You can skip the creating of the new array with map.
You can definitely use a forEach loop if you wanted to, the code will just be a little different. Using map is not necessary if you like how the new code looks.
import backpackObjectArray from "./components/data.js";
const main = document.querySelector(".maincontent");
backpackObjectArray.forEach((backpack) => {
let backpackArticle = document.createElement("article");
backpackArticle.classList.add("backpack");
// Set article ID to the backpack.id property
backpackArticle.setAttribute("id", backpack.id);
backpackArticle.innerHTML = `
<figure class="backpack__image">
<img src=${backpack.image} alt="" />
</figure>
<h1 class="backpack__name">${backpack.name}</h1>
<ul class="backpack__features">
<li class="packprop backpack__volume">Volume:<span> ${
backpack.volume
}l</span></li>
<li class="packprop backpack__color">Color:<span> ${
backpack.color
}</span></li>
<li class="backpack__age">Age:<span> ${backpack.backpackAge()} days old</span></li>
<li class="packprop backpack__pockets">Number of pockets:<span> ${
backpack.pocketNum
}</span></li>
<li class="packprop backpack__strap">Left strap length:<span> ${
backpack.strapLength.left
} inches</span></li>
<li class="packprop backpack__strap">Right strap length:<span> ${
backpack.strapLength.right
} inches</span></li>
<li class="feature backpack__lid">Lid status:<span> ${
backpack.lidOpen ? "open" : "closed"
}</span></li>
</ul>
`;
main.append(backpackArticle);
});
EDIT
Sorry, I havn't read your question carefully enough it seems. In your case, yes, you can interchange .map
with .forEach
and append the created elements directly without storing them in an intermediate array.
However, I'll leave the rest as it is, maybe someone finds it useful.
As a somewhat general answer, "yes, you could use .forEach
and get the same results". And you can also do it with .reduce
. However, if you want to have a list of results from a list of sources (as in your example), .map
is the way to go.
I am going to answer your question in a more general way, because it appears to me you are asking about the difference between
.forEach
and.map
in general.
Every method on Array.prototype
is there for a purpose. The purpose of .map
is to project (or "map", hence the name) a function over all items of a list. So if you want to go from a list of values to a list of other values, you can use .map
.
const sources = [1, 2, 3, 4, 5];
const results = sources.map(n => n + 1);
console.log(results); // logs [2, 3, 4, 5, 6]
To get the same with .forEach
, you'd have the same number of variables but two steps more you have to program: One for creating the results
array, one for adding the items manually to it.
const sources = [1, 2, 3, 4, 5];
const results = [];
sources.forEach(n => {
results.push(n);
});
console.log(results);
By direct comparison you can easily see that using .forEach
results slightly more code which is less declarative and more imperative in style.
As mentioned earlier, you could as well use .reduce
to map a function over a value and accumulate that into a resulting list. In fact, a vast amount of operations can be written by utilizing .reduce
. If you're curious, search for transducers
, there are several libraries in various languages available.
But back to the example using reduce
:
const sources = [1, 2, 3, 4, 5];
const results = sources.reduce((acc, n) => acc.concat(n + 1), []);
console.log(results); // logs [2, 3, 4, 5, 6]