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

问题描述 投票:0回答:4

我有一个带有内部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前置于第一个元素?

javascript html href
4个回答
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>元素,因此,当您将锚元素与字符串连接起来时,锚元素将被转换为实际链接(as described here)。


2
投票

如果稍微更改代码,它将变得更少代码并且有效。您不必为此使用reduce。这样你就不会摆弄初始值和累积值,只需将列表锚点转换为hrefs列表并加入......

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>

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>

1
投票

为什么会发生这种情况是因为reduce中的initialValue是可选的,如果没有传递,它会将数组的第一个索引作为初始值。因此,如果您记录第一个索引并且toString它,您将看到完整的URL以及哈希。尝试

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

Here's规范说:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.