Отличить DOM-элемент от объекта
Есть функция is, которая проверяет, удовлетворяет ли указанным параметрам DOM-элемент.
Ну например в jQuery: $("body").is(document.body) //→ true Пишу подобную функцию, но с возможностью указать объект с набором свойств для сравнения: //сравниваем свойства $("html").is({lang: "ru-RU"}) //сравниваем атрибуты $("html").is('[lang="ru-RU"]') И тут возникает проблема: $("html").is({nodeType: 1, nodeName: "html"}) как отличить DOM-объект от обычного объекта? Из-за IE простой проверкой node instanceof Node не обойтись, пришлось городить кучу условий://для IE<8 function isNode(arg) { return Boolean(typeof arg == "object" && !(arg instanceof Object) && arg.nodeType); } Есть ли способ сделать лучше? |
function isNode( obj ) { var documentElement = ( obj ? obj.ownerDocument || obj : 0 ).documentElement; return documentElement ? documentElement.nodeName === "HTML" : false; } |
На свойстве ownerDocument сломается:
function isNode( obj ) { var documentElement = ( obj ? obj.ownerDocument || obj : 0 ).documentElement; return documentElement ? documentElement.nodeName === "HTML" : false; } alert(isNode({ownerDocument: document})) // true Я в надежде, что всплывёт какой-нибудь трюк, типа: Array.isArray = function (obj) { return Object.prototype.toString.call(obj) == "[object Array]"; }; |
Можно воспользоваться тем, что IE не даёт выполнить стандартные js-методы в контексте не JScript-объектов.
alert([].slice.call(document.body)) Если вылетела ошибка, значит не обычный объект, для верности можно ещё проверить какой-нибудь tagName. |
Первое что пришло в голову поиграться с nodeType.
function isNode ( node ) { var nodeType = node && node.nodeType, isNode = true; if ( nodeType !== 1 || nodeType !== 9 ) { return !isNode; } try { delete node.nodeType; isNode = node.nodeType === nodeType; node.nodeType = nodeType; } catch ( e ) {} return isNode; } Еще интересным является, то что в IE, у dom элемента отсутствует конструктор function isNode ( node ) { if ( !node ) return false; var type = Object.prototype.toString.call( node ).toLowerCase().slice(8,-1); return (type == "object" && node.constructor == null && typeof node.nodeType == "number") || (/^html/.test( type ) && !/collection$/.test( type ) || type == "global"); } |
delete только в IE7 для свойств DOM-элементов приведет к ошибке, а
[].slice.call(node) — в IE7,8, тогда вариант без try-catch: typeof obj == "object" && !(obj instanceof Object)для этих браузеров привлекательнее мне кажется, под такое условие только null еще попадает. |
А проверить наличие какой-нибудь функции, типа getElementById или cloneNode?
Или речь не только про теги? |
Да это понятно, что можно напроверять наличие кучи свойств и методов, но опять же, допустим напишем:
function isNode(obj) { return "hasChildNodes" in obj; } а кто-нибудь додумается сделать: $(…).is({hasChildNodes: false}) дополнительными проверками конечно сведем вероятность неправильного результата к минимуму, но тему создавал в надежде, что найдем какое-нибудь интересное решение, как в случае с isArray :) |
Часовой пояс GMT +3, время: 02:51. |