当与reduce一起使用时,为什么getAttribute('href')返回完整的URL?

时间:2018-09-06 10:25:29

标签: javascript html href

我有一个具有内部ID的锚点列表,我想使用.querySelectorAll()选择所有目标,例如:

const targets = document.querySelectorAll('#target-1, #target-2, …')

为准备此查询,我使用了reduce

anchors.reduce((previous, current, index) =>
    index === 0 ?
        current.getAttribute('href') :
        previous + ', ' + current.getAttribute('href')
)

这几乎可行,但是有一个奇怪的问题,结果看起来像这样:

https://full-url.com/#target-1, #target-2, #target-3

当我只跑步时:

targets[0].getAttribute('href')

…它返回预期的结果:

target-1

您可以自己尝试:

const anchors = Array.from(document.querySelectorAll('a'));

console.log(anchors[0].getAttribute('href'));

console.log(anchors.reduce((previous, current, index) => index === 0 ? current.getAttribute('href') : previous + ', ' + current.getAttribute('href')));
<a href="#target-1"></a>
<a href="#target-2"></a>
<a href="#target-3"></a>


至少在macOS上的Chrome,Safari和Firefox中会发生这种情况。

为什么完整的URL放在第一个元素之前?

4 个答案:

答案 0 :(得分:3)

发生这种情况是因为reduce需要传递一个初始值。尝试传递空字符串:

const anchors = Array.from(document.querySelectorAll('a'));
const first = anchors[0].getAttribute('href');
const all = anchors.reduce((previous, current, index) => index === 0 ? current.getAttribute('href') : previous + ', ' + current.getAttribute('href'), "");

/* The first 'href' value. */
console.log(first);

/* All 'href' values. */
console.log(all);

/* When concatenating an <a> element with a string, a link is returned. */
console.log(anchors[0] + "");
<a href="#target-1"></a>
<a href="#target-2"></a>
<a href="#target-3"></a>

如果不传递初始值,则使用数组的第一个元素。由于数组中的元素是<a>元素,因此会在整个URL前面加上前缀,因为当您将锚元素与字符串连接时,该锚元素会转换为实际链接(as described here)。 / p>

答案 1 :(得分:2)

如果稍微更改代码,它将减少代码并可以使用。您不必为此使用reduce。这样,您就不必摆弄初始值和累加值,只需将列表锚点转换为其中href个列表  并加入…

const anchors = Array.from(document.querySelectorAll('a'));

const str = anchors.map(a => a.getAttribute('href')).join(',');
console.log(str);
<a href="#target-1"></a>
<a href="#target-2"></a>
<a href="#target-3"></a>

答案 2 :(得分:1)

您必须将空字符串作为初始值传递给回调函数:

let anchors = Array.from(document.querySelectorAll('a'));

 anchors = anchors.reduce((previous, current, index) => index === 0 ? current.getAttribute('href') : previous + ', ' + current.getAttribute('href'),"");
 console.log(anchors)
<a href="#target-1"></a>
<a href="#target-2"></a>
<a href="#target-3"></a>

答案 3 :(得分:1)

发生这种情况的原因是因为reduce中的initialValue是可选的,如果未传递,它将数组的第一个索引作为初始值。因此,如果您记录第一个索引并使其toString,则将看到完整的URL和哈希值。试试

console.log(anchors[0].toString())

Here's规格说明:

  

用作回调的第一次调用的第一个参数的值。如果未提供初始值,则将使用数组中的第一个元素。在没有初始值的空数组上调用reduce()是错误的。

有关正确的代码,请参见Angel's answer.