我有一个具有内部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放在第一个元素之前?
答案 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.