给定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`而不修改本机函数?
如果使用.querySelectorAll()
,所需的模式将接受变量,并将iterable的内容扩展为数组;这将同等对待.getElementsByTagName()
,.getElementsByClassName()
,.getElementsByTagName()
,.getElementsByName()
;或者将.querySelector()
返回的单个值设置为数组的元素。
注意,目前的工作解决方案是
div.length ? div : [div]
如果div
具有div
属性(可能是可迭代的),则迭代.length
,但只有.length
属性而不是iterable
; else将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]
属性?< / LI>
或者,考虑到iterable
或不iterable
的对象之间的差异,上面的方法是否可能是最简单的?
答案 0 :(得分:1)
我会做更多或更少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
}