Отличить 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, время: 13:47. |