晚上好。 我是一个JavaScript新手。 我坚持使用以下函数,试图获取一个值(dom树的一部分)。 而不是接收有用的值我只获得0 / undefined。 我在互联网上寻找解决方案,甚至在这里,但我找不到一个类似我的案例。 我怎么能正确实现这个?有什么建议吗? 非常感谢你提前。 最佳G。
var findNodeForAttributeValue = function (node, innerXmlAttributeName, innerXmlAttributeValue) {
var indirectReturnVar='0';
if ((node.nodeType === 1)&&(node.hasAttribute(innerXmlAttributeName))) {
if (node.getAttribute(innerXmlAttributeName)==innerXmlAttributeValue) {
indirectReturnVar=node;
return indirectReturnVar;
}
}
if((node.hasChildNodes())&&(node.firstChild!=null)) {
Array.forEach ( node.childNodes, function (children) {
findNodeForAttributeValue(children, innerXmlAttributeName, innerXmlAttributeValue);
} );
return indirectReturnVar;
}
}
更新的代码:
var findNodeForAttributeValue = function (node, innerXmlAttributeName, innerXmlAttributeValue) {
var indirectReturnVar='0';
if ((node.nodeType === 1) && (node.hasAttribute(innerXmlAttributeName))) {
if (node.getAttribute(innerXmlAttributeName) == innerXmlAttributeValue) {
indirectReturnVar = node;
return indirectReturnVar;
}
}
if ((node.hasChildNodes()) && (node.firstChild != null)) {
for (var fi=0, fiLen=node.childNodes.length; fi<fiLen; fi++) {
findNodeForAttributeValue(node.childNodes[fi], innerXmlAttributeName, innerXmlAttributeValue);
}
return indirectReturnVar;
}
}
答案 0 :(得分:0)
当你这样做时:
> Array.forEach ( node.childNodes .. )
forEach 是 Array.prototype 上的Array实例的方法。 childNodes属性是NodeList,不是数组。
在某些支持ES5的浏览器中,您可以执行以下操作:
Array.prototype.forEach.call(childNodes, ...)
但不能保证工作(并且在IE 8及更低版本中会失败)。所以只需使用for循环:
for (var i=0, iLen=node.childNodes.length; i<iLen; i++) {
// do stuff with node.childNodes[i];
}
修复更新后的代码:
function findNodeForAttributeValue (node, innerXmlAttributeName, innerXmlAttributeValue) {
使用函数声明,我不明白你为什么使用带赋值的表达式。此外,较短的变量名称将使生活更轻松,我可能会做类似的事情:
function getNodeByAttributeValue (node, att, value)
如果您希望变量具有真值,只需将其设置为true即可。在这种情况下,你想要它假,所以要么保持未定义或将其设置为 null (因为大多数DOM方法如果没有得到匹配的元素则返回null):
var indirectReturnVar = null;
这个块很好。
if ((node.nodeType === 1) && (node.hasAttribute(innerXmlAttributeName))) {
if (node.getAttribute(innerXmlAttributeName) == innerXmlAttributeValue) {
indirectReturnVar = node;
return indirectReturnVar;
}
}
if ((node.hasChildNodes()) && (node.firstChild != null)) {
这个位需要修改。仅在 indirectReturnVar 为假时保持循环:
for (var fi=0, fiLen=node.childNodes.length; fi<fiLen && !indirectReturnVar; fi++) {
将递归函数的返回值分配给 indirectReturnVar ,否则它会在以太中丢失。
indirectReturnVar = findNodeForAttributeValue(node.childNodes[fi], innerXmlAttributeName, innerXmlAttributeValue);
}
}
返回外部递归循环的值。它只会循环,直到它找到匹配的节点或用完节点。
return indirectReturnVar;
}
答案 1 :(得分:0)
在find1
之下,具有搜索功能f
,将对所提供的node
进行调用,并对每个节点childNodes
进行一次调用。当f
返回true
时,返回node
。否则,给出undefined
表示没有找到结果的信号。
const find1 = (f, node, cursor = 0) =>
node.nodeType === 1 && f (node)
? node
: cursor === node.childNodes.length
? undefined
: find1 (f, node.childNodes[cursor]) || find1 (f, node, cursor + 1)
console.log
( find1
( node => node.tagName === 'P'
, document
)
// <p>first paragraph</p>
, find1
( node => node.textContent === 'and a span'
, document
)
// <span>and a span</span>
, find1
( node => node.getAttribute('class') === 'last'
, document
)
// <p class="last">last paragraph</p>
)
<div id="main">
<!-- comment -->
<h1>title</h1>
<p>first paragraph</p>
<p>second paragraph <span>and a span</span></p>
<p class="last">last paragraph</p>
<div>
find1
以上不限于按特定的属性和值搜索节点。而是由用户提供的lambda允许程序员将find1
引向其目标。
如果我们要查找所有结果怎么办?在findAll
下返回所有匹配结果的数组
const findAll = (f, node) =>
{ const loop = function* (node)
{ if (node.nodeType === 1 && f (node))
yield node
for (const child of node.childNodes)
yield* loop (child)
}
return Array.from (loop (node))
}
console.log
( findAll
( node => node.tagName === 'P'
, document
)
// [ <p>first paragraph</p>
// , <p>second paragraph<span>...</span></p>
// , <p class="last">last paragraph</p>
// ]
, findAll
( node => node.getAttribute('class') === 'last'
, document
)
// [ <p class="last">last paragraph</p> ]
)
<div id="main">
<!-- comment -->
<h1>title</h1>
<p>first paragraph</p>
<p>second paragraph <span>and a span</span></p>
<p class="last">last paragraph</p>
<div>
find1
和findAll
之类的高阶函数非常有用,因为它们可以以各种有用的方式进行专门化。
const findByTag = (tagName, node) =>
findAll
( node => node.tagName === tagName.toUpperCase()
, node
)
const findByAttrValue = (attr, value, node) =>
findAll
( node => node.getAttribute (attr) === value
, node
)
console.log
( findByTag ('p', document)
// [ '<p>...</p>', '<p>...</p>', '<p>...</p>' ]
, findByTag ('h1', document)
// [ '<h1>title</h1>' ]
, findByTag ('strong', document)
// []
, findByAttrValue ('class', 'last', document)
// [ <p class="last">last paragraph</p> ]
, findByAttrValue ('id', 'main', document)
// [ <div id="main">...</div> ]
, findByAttrValue ('class', 'first', document)
// []
)