给定 html
<div></div>
<div></div>
调用
document.querySelector("div")
返回第一个 div
元素,其中 .length
不是返回值的属性。调用
document.querySelectorAll()
返回具有 NodeList
属性的 .length
。.querySelector()
和.querySelectorAll()
这两个返回值的区别在于前者不是可迭代的;尝试使用 spread element
将元素扩展为数组时将引发错误。在以下示例中,请考虑
div
或 divs
是函数调用主体中接收的参数。因此,据我们所知,无法确定变量是否定义为 Element.querySelector()
、 Element.querySelectorAll()
、 document.querySelector()
或 document.querySelectorAll()
的结果;此外,只能使用 .querySelector()
检查 .querySelectorAll()
和 .length
之间的差异。var div = document.querySelector("div");
for (let el of div) {
console.log(".querySelector():", el)
}
<div></div>
<div></div>
日志
Uncaught TypeError: div[Symbol.iterator] is not a function
尽管
var div = document.querySelectorAll("div");
for (let el of div) {
console.log(".querySelectorAll():", el)
}
<div></div>
<div></div>
返回预期结果;也就是说,
document.querySelectorAll("div")
被扩展以填充可迭代数组。通过将
.querySelector()
设置为 div
的元素,我们可以在 Array
处获得预期结果[div]
在
for..of
iterable
参数处。最接近的方法是对两者使用相同的模式,或者
.querySelector()
或 .querySelectorAll()
使用 callback
的 Array.from()
和变量的 .tagName
和 spread element
。尽管这省略了可能已使用
.querySelector()
调用的其他选择器,例如 .querySelector("div.abc")
。var div = document.querySelector("div");
var divs = document.querySelectorAll("div");
var elems = Array.from({length:div.length || 1}, function(_, i) {
return [...div.parentElement.querySelectorAll(
(div.tagName || div[0].tagName))
][i]
});
for (let el of elems) {
console.log(".querySelector():", el)
}
elems = Array.from({length:divs.length || 1}, function(_, i) {
return [...divs[0].parentElement.querySelectorAll(
(divs.tagName || divs[0].tagName))
][i]
});
for (let el of elems) {
console.log("querySelectorAll:", el)
}
<div></div>
<div></div>
由于其他原因,这不能提供足够的准确性;
Element.querySelector()
本来可以传递给函数,而不是 document.querySelector()
,类似地对于 .querySelectorAll().
Not sure if it is possible to retrieve the exact selector passed to
.querySelector, All` 而不修改 native 函数?如果使用了
.querySelectorAll()
,则所需的模式将接受变量,并将可迭代的内容扩展为数组;这会将 .getElementsByTagName()
、 .getElementsByClassName()
、 .getElementsByTagName()
、 .getElementsByName()
视为相同;或者将 .querySelector()
返回的单个值设置为数组的元素。请注意,当前的工作解决方案是
div.length ? div : [div]
如果
div
具有 div
属性(可能是可迭代的),则迭代 .length
,尽管它只是具有 .length
属性而不是 iterable
;否则将 div
设置为数组的单个元素,一个可迭代的。var div = document.querySelector("div");
var divs = document.querySelectorAll("div");
var elems = div.length ? div : [div];
for (let el of elems) {
console.log(".querySelector():", el)
}
var elems = divs.length ? divs : [divs];
for (let el of elems) {
console.log("querySelectorAll:", el)
}
<div></div>
<div></div>
这可以实现吗
.length
? 可以工作解决方案的方法吗
[Symbol.iterator]
的 div
而不是 .length
? .spread element
或 rest element
是否有魔法可以允许省略检查对象的 .length
? Generator
、 Array.prototype.reduce()
或其他方法改变在将元素扩展为数组之前检查变量的 .length
或 [Symbol.iterator]
属性的需要吗? 或者,考虑到
iterable
或非 iterable
对象之间的差异,上述方法是否是最简洁的?
最佳答案
我或多或少会做what Array.from
does , 但检查 length
的类型而不是总是转换它:
const itemsOrSingle = items => {
const iteratorFn = items[Symbol.iterator]
if (iteratorFn) {
return Array.from(iteratorFn.call(items))
}
const length = items.length
if (typeof length !== 'number') {
return [items]
}
const result = []
for (let i = 0; i < length; i++) {
result.push(items[i])
}
return result
}
关于javascript - 将可迭代元素或不可迭代元素扩展为数组而不检查元素 .length,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40198807/