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

Posted

技术标签:

【中文标题】为啥在 innerHTML 中使用的 Array#map 输出中的额外逗号?【英文标题】:Why the extra comma in Array#map output used in innerHTML?为什么在 innerHTML 中使用的 Array#map 输出中的额外逗号? 【发布时间】:2019-01-28 04:24:39 【问题描述】:

之前的帖子提到了 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 一样没有意义。真的是伪装成mapforEach。第二个示例作为map 是有意义的,但会返回一个应有的数组,因此是逗号。你可能想要reduce map 方法返回一个数组[],然后您将其作为字符串应用,默认的 Array.toString 方法将逗号作为分隔符。你真的应该有类似data.map(getNameAge).join(' ') map 返回一个数组。 innerHTML 接受一个字符串。所以数组是stringified。使用join 您可以通过单击左侧的灰色大复选按钮来接受一个答案(如果对您有帮助)。如果您希望可以通过单击上方灰色三角形为任何好的答案的任何作者添加 +10 分 【参考方案1】:

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

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

下面是 map 的正确用法,joins 将结果数组转换为一个不带逗号的字符串:

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("");
&lt;div id="display2"&gt;&lt;/div&gt;

如果您希望使用&lt;br&gt;s 分隔元素而不是每行附加,您可以使用.join("&lt;br&gt;")。但是,使用列表在语义上更合适,并且可以更轻松地操作每个项目的内容(使用 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;

【讨论】:

【参考方案2】:

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

(1) map() 方法使用为每个数组元素调用函数的结果创建一个新数组。

(2) map() 方法按顺序为数组中的每个元素调用一次提供的函数。

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

尝试 1:

引用 (1):在此尝试中,您没有对 map 调用返回做任何事情,因此我们可以跳过它。

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

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

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

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

尝试 2

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

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

所以当map 的执行完成时,它将返回一个数组,其中包含每次调用getNameAge 函数时返回的值。在您的示例中["Name: John Age: 38", "Name: Mary Age: 33"]

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

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

【讨论】:

【参考方案3】:

在 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('');
&lt;div id="display2"&gt;&lt;/div&gt;

【讨论】:

以上是关于为啥在 innerHTML 中使用的 Array#map 输出中的额外逗号?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript - 使用 innerHTML 创建元素会复制它们。为啥? [关闭]

为啥我不能使用 onsubmit 来更改 innerHTML?

如何在 Laravel 中使用 innerHTML 打印数组

为啥 innerHTML 在 for 循环中不能正常工作?

为啥我无法在文档上设置 innerHTML? [复制]

为啥 Angular 2+ innerHTML 在单个语句中多次调用方法,如何解决这个问题