Regarding the problems described in the first example / requirement. Because getElementById exists only in the document node, since it uses caches that are provided only by the node tree as part of document . You have three options for finding a node tree that is not bound to document . Everyone suffers from 0 (log n), since they do not use document caching, this is almost there (you tried to use iFrame ).
One: node recursive walker.
The advantage is that it is a cross-browser interface
The downside is that it will always be 0 (log n) - if used on document
Javascript
function getElementById(node, id) { if (node.id === id) { return node; } var target; node = node.firstChild; while (node) { target = getElementById(node, id); if (target) { return target; } node = node.nextSibling; } return undefined; } function foo(html) { var el = document.createElement("div"); el.innerHTML = html; var target = getElementById(el, "target"); if (target) { console.log(target); } } foo('<div id="nottarget1"><div id="nottarget2"><div id="nottarget3"><div id="nottarget4"><div id="target">Target</div></div></div></div></div>');
On jsfiddle
Two: using querySelector , which is available for each element.
The advantage is that it requires less code.
The downside is that it requires IE8 + (and IE8 itself has limitations on CSS request)
Javascript
function getElementById(node, id) { return node.querySelector("#" + id); } function foo(html) { var el = document.createElement("div"); el.innerHTML = html; var target = getElementById(el, "target"); if (target) { console.log(target); } } foo('<div id="nottarget1"><div id="nottarget2"><div id="nottarget3"><div id="nottarget4"><div id="target">Target</div></div></div></div></div>');
Jsfiddle on
Three - use TreeWalker
The downside is that it requires IE9 +, is less understood (often forgotten) than the previous ones, and requires more code than querySelector
Javascript
function getElementById(node, id) { return document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT, { acceptNode: function (n) { if (n.id === id) { return NodeFilter.FILTER_ACCEPT; } } }, false).nextNode(); } function foo(html) { var el = document.createElement("div"); el.innerHTML = html; var target = getElementById(el, "target"); if (target) { console.log(target); } } foo('<div id="nottarget1"><div id="nottarget2"><div id="nottarget3"><div id="nottarget4"><div id="target">Target</div></div></div></div></div>');
Jsfiddle on
Now about the performance of these methods see this jsperf
Note. The execution of the three methods will change dramatically if the nodes are part of a document !
As for your second wish, what you described is a dumb point due to the nature of document caches.
Update: If asynchrony is not a problem for your requirement, you can do it using iFrame .
The advantage is that you can now use getElementById
The disadvantage is the huge overhead of creating and destroying an iFrame
Javascript
var getElementById = (function () { var parent = document.body || document.documentElement, javascript = "javascript"; return function (node, id, func) { var iframe = document.createElement("iframe"); iframe.style.display = "none"; iframe.src = javascript + ":"; iframe.onload = function () { iframe.contentWindow.document.body.appendChild(node); func(iframe.contentWindow.document.getElementById(id)); parent.removeChild(iframe); }; parent.appendChild(iframe); }; }()); function foo(html) { var el = document.createElement("div"); el.innerHTML = html; getElementById(el, "target", function (target) { if (target) { console.log(target); } }); } foo('<div id="nottarget1"><div id="nottarget2"><div id="nottarget3"><div id="nottarget4"><div id="target">Target</div></div></div></div></div>')
;
Jsfiddle on