Folgendes habe ich herausgefunden:
var isHTMLElement = (function () {
if ("HTMLElement" in window) {
// Voilà. Quick and easy. And reliable.
return function (el) {return el instanceof HTMLElement;};
} else if ((document.createElement("a")).constructor) {
// We can access an element's constructor. So, this is not IE7
var ElementConstructors = {}, nodeName;
return function (el) {
return el && typeof el.nodeName === "string" &&
(el instanceof ((nodeName = el.nodeName.toLowerCase()) in ElementConstructors
? ElementConstructors[nodeName]
: (ElementConstructors[nodeName] = (document.createElement(nodeName)).constructor)))
}
} else {
// Not that reliable, but we don't seem to have another choice. Probably IE7
return function (el) {
return typeof el === "object" && el.nodeType === 1 && typeof el.nodeName === "string";
}
}
})();
Um die Leistung zu verbessern, habe ich eine selbstaufrufende Funktion erstellt, die die Funktionen des Browsers nur einmal testet und die entsprechende Funktion entsprechend zuweist.
Der erste Test sollte in den meisten modernen Browsern funktionieren und wurde hier bereits besprochen. Es wird nur getestet, ob das Element eine Instanz von ist HTMLElement
. Sehr einfach.
Der zweite ist der interessanteste. Dies ist seine Kernfunktionalität:
return el instanceof (document.createElement(el.nodeName)).constructor
Es wird geprüft, ob el eine Instanz des Konstrukts ist, das es vorgibt zu sein. Dazu benötigen wir Zugriff auf den Konstruktor eines Elements. Deshalb testen wir dies in der if-Anweisung. IE7 zum Beispiel schlägt fehl, weil (document.createElement("a")).constructor
es undefined
in IE7 ist.
Das Problem bei diesem Ansatz ist, dass dies document.createElement
nicht die schnellste Funktion ist und Ihre Anwendung leicht verlangsamen kann, wenn Sie viele Elemente damit testen. Um dies zu lösen, habe ich beschlossen, die Konstruktoren zwischenzuspeichern. Das Objekt ElementConstructors
hat Knotennamen als Schlüssel mit den entsprechenden Konstruktoren als Werte. Wenn ein Konstruktor bereits zwischengespeichert ist, verwendet er ihn aus dem Cache. Andernfalls erstellt er das Element, speichert seinen Konstruktor für den zukünftigen Zugriff zwischen und testet ihn anschließend.
Der dritte Test ist der unangenehme Fallback. Es wird getestet, ob el ein ist object
, eine nodeType
Eigenschaft auf gesetzt ist 1
und eine Zeichenfolge als nodeName
. Dies ist natürlich nicht sehr zuverlässig, aber die überwiegende Mehrheit der Benutzer sollte noch nicht einmal zurückgreifen.
Dies ist der zuverlässigste Ansatz, den ich mir ausgedacht habe, während die Leistung so hoch wie möglich gehalten wurde.