如何在不使用 map() 数组方法的情况下获得相同的结果?在这里使用 map() 数组方法的意义到底是什么?

How can I achieve the same outcome without using map() array method? What exactly is the significance of using map() array method here?

可在此处找到源内容:https://github.com/LinkedInLearning/javascript-essential-training-2832077/tree/main/08_17。有问题的代码就是这个块:

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);
}
)

本质上,是不是只用forEach循环就可以输出和我们使用map()数组方法一样的结果,即为每个对象输出一篇HTML篇文章?

*Pseudo-code* Array.prototype.map(function(ea){return backpackArticle}) 将简单地创建一个新数组并在每次迭代中包含您 return 的任何内容。

您可以通过其他方式实现相同的目的,但是,如前所述,需要更多代码。实际上,本例中的 'significance' 只是用更少的代码实现了预期的结果。

我认为在您的示例中,它是显式创建一个新数组,然后使用 forEach 将每个 backpackArticle 显式附加到 <main>。您可以跳过使用 map 创建新数组。

如果愿意,您绝对可以使用 forEach 循环,只是代码会稍有不同。如果您喜欢新代码的外观,则无需使用地图。

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);
});

编辑

抱歉,我似乎没有足够仔细地阅读您的问题。在您的情况下,是的,您可以将 .map.forEach 互换并直接附加创建的元素而不将它们存储在中间数组中。

但是,我将保留其余部分,也许有人觉得它有用。


作为一个比较笼统的回答,“是的,您可以使用 .forEach 并获得相同的结果”。你也可以用 .reduce 来完成。但是,如果您想从源列表中获得结果列表(如您的示例所示),.map 是可行的方法。

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.

Array.prototype 上的每个方法都是有目的的。 .map 的目的是在列表的所有项目上投影(或“映射”,因此得名)一个函数。因此,如果您想从值列表转到其他值列表,可以使用 .map.

const sources = [1, 2, 3, 4, 5];
const results = sources.map(n => n + 1);
console.log(results); // logs [2, 3, 4, 5, 6]

要获得与 .forEach 相同的结果,您将拥有相同数量的变量,但您必须多执行两步编程:一步用于创建 results 数组,一步用于添加项目手动添加。

const sources = [1, 2, 3, 4, 5];
const results = [];
sources.forEach(n => {
  results.push(n);
});
console.log(results);

通过直接比较,您可以很容易地看到使用 .forEach 会产生稍微多一些的代码,这些代码的声明性较低,但在风格上更具命令性。

如前所述,您也可以使用 .reduce 将一个函数映射到一个值并将其累加到结果列表中。事实上,利用.reduce可以写出大量的操作。如果您好奇,请搜索 transducers,这里有多个不同语言的库。

但回到使用 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]