我有一个带有内部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前置于第一个元素?
发生这种情况是因为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)。
如果稍微更改代码,它将变得更少代码并且有效。您不必为此使用reduce
。这样你就不会摆弄初始值和累积值,只需将列表锚点转换为href
s列表并加入......
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>
您必须将空字符串作为初始值传递给回调函数:
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>
为什么会发生这种情况是因为reduce中的initialValue是可选的,如果没有传递,它会将数组的第一个索引作为初始值。因此,如果您记录第一个索引并且toString它,您将看到完整的URL以及哈希。尝试
console.log(anchors[0].toString())
Here's规范说:
用作第一次调用回调的第一个参数的值。如果未提供初始值,则将使用数组中的第一个元素。在没有初始值的空数组上调用reduce()是一个错误。
有关正确的代码,请参阅Angel's answer.