Out of curiosity I ran your code against both jQuery's .index()
and my below code:
function findRow3(node)
{
var i = 1;
while (node = node.previousSibling) {
if (node.nodeType === 1) { ++i }
}
return i;
}
Jump to jsperf results
It turns out that jQuery is roughly 50% slower than your implementation (on Chrome/Mac) and mine arguably topped it by 1%.
Edit
Couldn't quite let this one go, so I've added two more approaches:
Using Array.indexOf
[].indexOf.call(node.parentNode.children, node);
Improvement on my earlier experimental code, as seen in HBP's answer, the DOMNodeList
is treated like an array and it uses Array.indexOf()
to determine the position within its .parentNode.children
which are all elements. My first attempt was using .parentNode.childNodes
but that gives incorrect results due to text nodes.
Using previousElementSibling
Inspired by user1689607's answer, recent browsers have another property besides .previousSibling
called .previousElementSibling
, which does both original statements in one. IE <= 8 doesn't have this property, but .previousSibling
already acts as such, therefore a feature detection would work.
(function() {
// feature detection
// use previousElementSibling where available, IE <=8 can safely use previousSibling
var prop = document.body.previousElementSibling ? 'previousElementSibling' : 'previousSibling';
getElementIndex = function(node) {
var i = 1;
while (node = node[prop]) { ++i }
return i;
}
Conclusion
Using Array.indexOf()
is not supported on IE <= 8 browsers, and the emulation is simply not fast enough; however, it does give 20% performance improvement.
Using feature detection and .previousElementSibling
yields a 7x improvement (on Chrome), I have yet to test it on IE8.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…