在不检查元素 .length 的情况下将可迭代元素或不可迭代元素扩展到数组中
Expand an iterable element or non-iterable element into an array without checking element .length
给定 html
<div></div>
<div></div>
调用 document.querySelector("div")
return 第一个 div
元素,其中 .length
不是 return 值的 属性。
调用 document.querySelectorAll()
return 一个 NodeList
有一个 .length
属性.
.querySelector()
和.querySelectorAll()
的两个return值的区别在于前者不是可迭代的;尝试使用 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>
return的预期结果;也就是说,document.querySelectorAll("div")
被扩展以填充可迭代数组。
通过将 div
设置为 Array
的元素,我们可以在 .querySelector()
处获得预期结果
[div]
在 for..of
iterable
参数。
最接近于对两者或 .querySelector()
或 .querySelectorAll()
使用相同模式的是使用 Array.from()
的 callback
和 .tagName
的 .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()
,则将可迭代对象的内容扩展到数组中;这将对待 .getElementsByTagName()
、.getElementsByClassName()
、.getElementsByTagName()
、.getElementsByName()
相同;或将由 .querySelector()
编辑的单个值 return 设置为数组的元素。
注意,当前的工作解决方案是
div.length ? div : [div]
如果 div
有一个 .length
属性,它迭代 div
,可能是一个可迭代的,尽管只有一个 .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
?
- 没有在同一行中引用该元素三次?
能否提供解决方案的方法
- 有待改进;那就是应该检查
div
的 [Symbol.iterator]
而不是 .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
}
给定 html
<div></div>
<div></div>
调用 document.querySelector("div")
return 第一个 div
元素,其中 .length
不是 return 值的 属性。
调用 document.querySelectorAll()
return 一个 NodeList
有一个 .length
属性.
.querySelector()
和.querySelectorAll()
的两个return值的区别在于前者不是可迭代的;尝试使用 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>
return的预期结果;也就是说,document.querySelectorAll("div")
被扩展以填充可迭代数组。
通过将 div
设置为 Array
.querySelector()
处获得预期结果
[div]
在 for..of
iterable
参数。
最接近于对两者或 .querySelector()
或 .querySelectorAll()
使用相同模式的是使用 Array.from()
的 callback
和 .tagName
的 .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()
,则将可迭代对象的内容扩展到数组中;这将对待 .getElementsByTagName()
、.getElementsByClassName()
、.getElementsByTagName()
、.getElementsByName()
相同;或将由 .querySelector()
编辑的单个值 return 设置为数组的元素。
注意,当前的工作解决方案是
div.length ? div : [div]
如果 div
有一个 .length
属性,它迭代 div
,可能是一个可迭代的,尽管只有一个 .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
? - 没有在同一行中引用该元素三次?
能否提供解决方案的方法
- 有待改进;那就是应该检查
div
的[Symbol.iterator]
而不是.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
}