Вот что я понял:
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 object
, имеет ли nodeType
свойство свойство 1
и строку как nodeName
. Конечно, это не очень надежно, но подавляющее большинство пользователей не должно даже отступать.
Это самый надежный подход, который я предложил, при этом сохраняя максимально высокую производительность.