¿Cómo se comprueba si un objeto JavaScript es un objeto DOM?

Resuelto Jonathan Lonowski asked hace 15 años • 38 respuestas

Estoy intentando conseguir:

document.createElement('div')  //=> true
{tagName: 'foobar something'}  //=> false

En mis propios scripts, solía usar esto ya que nunca lo necesité tagNamecomo propiedad:

if (!object.tagName) throw ...;

Entonces, para el segundo objeto, se me ocurrió lo siguiente como una solución rápida, que en su mayoría funciona. ;)

El problema es que depende de que los navegadores apliquen propiedades de solo lectura, algo que no todos hacen.

function isDOM(obj) {
  var tag = obj.tagName;
  try {
    obj.tagName = '';  // Read-only for DOM, should throw exception
    obj.tagName = tag; // Restore for normal objects
    return false;
  } catch (e) {
    return true;
  }
}

¿Existe un buen sustituto?

Jonathan Lonowski avatar Dec 21 '08 16:12 Jonathan Lonowski
Aceptado

Esto puede ser de interés:

function isElement(obj) {
  try {
    //Using W3 DOM2 (works for FF, Opera and Chrome)
    return obj instanceof HTMLElement;
  }
  catch(e){
    //Browsers not supporting W3 DOM2 don't have HTMLElement and
    //an exception is thrown and we end up here. Testing some
    //properties that all elements have (works on IE7)
    return (typeof obj==="object") &&
      (obj.nodeType===1) && (typeof obj.style === "object") &&
      (typeof obj.ownerDocument ==="object");
  }
}

Es parte del DOM, Nivel2 .

Actualización 2 : así es como lo implementé en mi propia biblioteca: (el código anterior no funcionó en Chrome, porque Node y HTMLElement son funciones en lugar del objeto esperado. Este código se prueba en FF3, IE7, Chrome 1 y Opera 9).

//Returns true if it is a DOM node
function isNode(o){
  return (
    typeof Node === "object" ? o instanceof Node : 
    o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
  );
}

//Returns true if it is a DOM element    
function isElement(o){
  return (
    typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
    o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
);
}
some avatar Dec 21 '2008 12:12 some

La respuesta aceptada es un poco complicada y no detecta todos los tipos de elementos HTML. Por ejemplo, los elementos SVG no son compatibles. Por el contrario, esta respuesta funciona tanto para HTML como para SVG, etc.

Véalo en acción aquí: https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}

Cereza en la parte superior: el código anterior es compatible con IE8.

Monarch Wadia avatar Apr 27 '2016 15:04 Monarch Wadia

No hay necesidad de hacks, simplemente puedes preguntar si un elemento es una instancia del elemento DOM :

const isDOM = el => el instanceof Element
Damjan Pavlica avatar Nov 28 '2016 17:11 Damjan Pavlica

Todas las soluciones anteriores y siguientes (incluida mi solución) tienen la posibilidad de ser incorrectas, especialmente en IE: es muy posible (re)definir algunos objetos/métodos/propiedades para imitar un nodo DOM que invalida la prueba.

Por eso, normalmente uso las pruebas de tipo pato: pruebo específicamente las cosas que uso. Por ejemplo, si quiero clonar un nodo, lo pruebo así:

if(typeof node == "object" && "nodeType" in node &&
   node.nodeType === 1 && node.cloneNode){
  // most probably this is a DOM node, we can clone it safely
  clonedNode = node.cloneNode(false);
}

Básicamente es una pequeña verificación de cordura + la prueba directa de un método (o propiedad) que planeo usar.

Por cierto, la prueba anterior es una buena prueba para los nodos DOM en todos los navegadores. Pero si quiere estar seguro, compruebe siempre la presencia de métodos y propiedades y verifique sus tipos.

EDITAR: IE usa objetos ActiveX para representar nodos, por lo que sus propiedades no se comportan como un verdadero objeto JavaScript, por ejemplo:

console.log(typeof node.cloneNode);              // object
console.log(node.cloneNode instanceof Function); // false

mientras que debería devolver "función" y truerespectivamente. La única forma de probar métodos es ver si están definidos.

Eugene Lazutkin avatar Dec 22 '2008 02:12 Eugene Lazutkin

Una forma sencilla de probar si una variable es un elemento DOM (sintaxis detallada, pero más tradicional :-)

function isDomEntity(entity) {
  if(typeof entity  === 'object' && entity.nodeType !== undefined){
     return true;
  }
  else{
     return false;
  }
}

O como sugirió HTMLGuy (sintaxis breve y limpia):

const isDomEntity = entity =>
  typeof entity === 'object' && entity.nodeType !== undefined
Roman avatar Jun 15 '2017 11:06 Roman