Це я зрозумів:
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";
}
}
})();
Для підвищення продуктивності я створив функцію самозванки, яка перевіряє можливості браузера лише один раз і відповідно призначає відповідну функцію.
Перший тест повинен працювати в більшості сучасних браузерів і тут вже йшлося. Він просто перевіряє, чи елемент є екземпляром HTMLElement
. Дуже прямо.
Другий - найцікавіший. Це його основна функціональність:
return el instanceof (document.createElement(el.nodeName)).constructor
Він перевіряє, чи el є примірником конструктора, на який він претендує. Для цього нам потрібен доступ до провідника елемента. Ось чому ми тестуємо це в if-Statement. Наприклад, IE7 не вдається, оскільки (document.createElement("a")).constructor
єundefined
в IE7.
Проблема такого підходу полягає в тому, що document.createElement
це насправді не найшвидша функція і може легко уповільнити вашу програму, якщо ви протестуєте багато елементів за допомогою неї. Щоб вирішити це, я вирішив кешувати конструктори. Об'єкт ElementConstructors
має nodeNames як ключі з відповідними конструкторами як значення. Якщо конструктор уже кешований, він використовує його з кешу, інакше він створює Елемент, кешує його конструктор для подальшого доступу та потім тестує проти нього.
Третє випробування - неприємний запас. Він перевіряє, чи el є an object
, має nodeType
властивість 1
та string якnodeName
. Звичайно, це не дуже надійно, але переважна більшість користувачів не повинні навіть відступати.
Це найнадійніший підхід, який я придумав, зберігаючи ефективність якнайбільше.