为什么在 innerHTML 中使用 Array#map 输出中的额外逗号?

Why the extra comma in Array#map output used in innerHTML?

之前的帖子提到了 toString() 方法如何在映射的每个项目之间放置逗号,并且可以通过使用 join(" ").

来解决这个问题

下面,尝试 2 在显示的对象之间添加逗号,而尝试 1 则没有。为什么是这样?

如何修改尝试 2 以使其输出复制尝试 1?

var data = [ {"name":"John","age":38}, {"name":"Mary","age":33}]

尝试 1(完美!):

data.map(function(e) {
   display2.innerHTML += "Name: " + e.name + " Age: " + e.age + "<br />";
})

输出:

Name: John Age: 38
Name: Mary Age: 33

尝试 2(在元素之间添加逗号 - 为什么?):

function getNameAge(e) {
  var nameAge = "Name: " + e.name + " Age: " + e.age + "<br />";
  return nameAge;
}

display2.innerHTML = data.map(getNameAge);

输出:

Name: John Age: 38
,Name: Mary Age: 33

第一个示例没有使用 map as intended,而是作为美化的 forEachmap 通过对数组中的每个项目应用一个函数并返回结果数组来工作,这在第一种情况下被忽略。目的是 map 的回调 returns 对元素进行所需的修改,而不是对外部变量产生副作用。

您的第二个示例是 map 的适当使用,因为您将返回的数组分配给了 属性。设置 innerHTML 将数组字符串化为逗号分隔的字符串;逗号分隔符是 Array.prototype.toString.

的默认值

下面是 map 的正确用法,它 join 将结果数组变成一个没有逗号的字符串:

const data = [{"name": "John", "age": 38}, {"name": "Mary", "age": 33}];
const display2 = document.getElementById("display2");

display2.innerHTML = data.map(e => `Name: ${e.name} Age: ${e.age}<br>`).join("");
<div id="display2"></div>

如果您更喜欢 <br>s 分隔元素而不是每行附加,您可以使用 .join("<br>")。但是,使用列表在语义上更合适,并且可以更轻松地操作每个项目的内容(通常使用 CSS 删除项目符号):

const data = [{"name": "John", "age": 38}, {"name": "Mary", "age": 33}];

const list = data.map(e => `<li>Name: ${e.name} Age: ${e.age}</li>`);
document.body.innerHTML = `<ul>${list.join("")}</ul>`;
ul {
  list-style-type: none;
  padding: 0;
}

首先看一下map函数定义(https://www.w3schools.com/jsref/jsref_map.asp):

(1) The map() method creates a new array with the results of calling a function for every array element.

(2) The map() method calls the provided function once for each element in an array, in order.

现在,让我们分析一下您在两次尝试中都做了什么:

尝试 1:

引用 (1):在这次尝试中,您没有对 map 调用 return 执行任何操作,因此我们可以跳过它。

quote (2): 对于数组中的每个元素,map 函数将调用您作为参数传递的函数:

function(e) {
    display2.innerHTML += "Name: " + e.name + " Age: " + e.age + "<br />";
}

因此,对于 data 上的每个项目,这段代码将附加到 display2innerHTML 属性 您编写的字符串 ("Name: " + ...) ,最后留下预期的输出:

Name: John Age: 38
Name: Mary Age: 33

尝试 2

quote (2): 对于数组中的每个元素,map 函数将调用您作为参数传递的函数:

function getNameAge(e) {
    var nameAge = "Name: " + e.name + " Age: " + e.age + "<br />";
    return nameAge;
}

因此,当 map 的执行完成时,它将 return 一个包含值的数组 return 在每次调用 getNameAge 函数时编辑。在你的例子中 ["Name: John Age: 38", "Name: Mary Age: 33"].

quote (1): 在此尝试中,您正在使用 map 函数 return 因为您将其分配给 innerHTML 属性 of [=19] =].由于 innerHTML 是字符串 属性 而 map return 是 Array,因此需要将其转换为字符串(隐式调用它是 toString方法)。数组的 toString 方法将打印由逗号分隔的数组值(参见 https://www.w3schools.com/jsref/jsref_tostring_array.asp),生成意外输出:

Name: John Age: 38
,Name: Mary Age: 33

在 ATTEMPT 2 中,js 将数组隐式转换为字符串(并使用逗号作为默认分隔符)。因此,您可以在设置 innerHTML 之前通过添加 join(''):

将数组显式转换为字符串
display2.innerHTML = data.map(getNameAge).join('');

const data = [ {"name":"John","age":38}, {"name":"Mary","age":33}];
const display2 = document.getElementById("display2");

function getNameAge(e) {
    var nameAge = "Name: " + e.name + " Age: " + e.age + "<br />";
    return nameAge;
}

display2.innerHTML = data.map(getNameAge).join('');
<div id="display2"></div>