Comment vérifiez-vous si un objet JavaScript est un objet DOM?

247

J'essaye d'obtenir:

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

Dans mes propres scripts, j'utilisais juste ceci car je n'avais jamais besoin tagNamed'une propriété:

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

Donc, pour le deuxième objet, j'ai trouvé ce qui suit comme une solution rapide - qui fonctionne principalement. ;)

Le problème est que cela dépend des navigateurs appliquant des propriétés en lecture seule, ce qui n'est pas le cas de tous.

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;
  }
}

Y a-t-il un bon substitut?

Jonathan Lonowski
la source
3
Suis-je obtus en me demandant si un "objet DOM" ne devrait pas couvrir non seulement les éléments mais aussi tous les nœuds (nœuds de texte, attributs, etc.)? Toutes les réponses et la façon dont vous avez posé la question ont tendance à suggérer que cette question concerne spécifiquement les éléments ...
Mike Rodent

Réponses:

300

Cela pourrait être intéressant:

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");
  }
}

Cela fait partie du DOM, Level2 .

Mise à jour 2 : voici comment je l'ai implémenté dans ma propre bibliothèque: (le code précédent ne fonctionnait pas dans Chrome, car Node et HTMLElement sont des fonctions au lieu de l'objet attendu. Ce code est testé dans FF3, IE7, Chrome 1 et 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"
);
}
certains
la source
11
Il convient de noter que cela ne fonctionnera pas sur les éléments appartenant à d'autres fenêtres / cadres. La frappe au canard est l'approche recommandée
Andy E
2
Vous pouvez le duper avec:function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
Kernel James
11
Fait WTF: Firefox 5 et versions antérieures reviennent truepour [] instanceof HTMLElement.
Rob W
6
Btw, HTMLElementest toujours un function, donc typeofvous jettera hors de la piste et exécutera la deuxième partie de l'instruction. Vous pouvez essayer si vous le souhaitez instanceof Object, car la fonction sera une instance de Object, ou simplement vérifier explicitement typeof === "function", car Nodeet HTMLElementsont toutes deux des fonctions d'objet natif.
Roland
2
Lorsque vous appelez isElement(0), il retourne 0, pas faux ... Pourquoi cela, et comment puis-je empêcher cela?
Jessica
68

Le code super-simple compatible IE8 suivant fonctionne parfaitement.

La réponse acceptée ne détecte pas tous les types d'éléments HTML. Par exemple, les éléments SVG ne sont pas pris en charge. En revanche, cette réponse fonctionne aussi bien pour HTML que SVG.

Voyez-le en action ici: https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}
Monarch Wadia
la source
3
'Element' n'est pas défini sur IE7
Dan
49
Je suis d'avis que quiconque utilise encore IE7 devrait passer les cinq secondes pour télécharger un meilleur navigateur au lieu de nous le faire investir des jours ou des semaines pour contourner son refus de faire face à son temps.
mopsyd
1
Je suis d'accord avec @mopsyd, mais l'auteur de la réponse déclare que cela fonctionne dans IE7, qui pourrait avoir besoin d'être mis à jour pour des raisons d'exactitude.
Lajos Meszaros
1
Mis à jour pour dire IE9. Je ne sais pas si IE8 le prend en charge.
Monarch Wadia
1
@MonarchWadia oui, il est pris en charge dans IE8. Mais notez que cela ne renvoie pas true pour l' documentélément (dans tous les navigateurs). si vous en avez besoin, vous devriez essayer:x instanceof Element || x instanceof HTMLDocument
S.Serpooshan
11

Toutes les solutions ci-dessus et ci-dessous (ma solution y compris) souffrent de la possibilité d'être incorrectes, en particulier sur IE - il est tout à fait possible de (re) définir certains objets / méthodes / propriétés pour imiter un nœud DOM rendant le test invalide.

Donc, d'habitude, j'utilise les tests de type canard: je teste spécifiquement pour les choses que j'utilise. Par exemple, si je veux cloner un nœud, je le teste comme ceci:

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);
}

Fondamentalement, c'est un petit test de santé mentale + le test direct d'une méthode (ou d'une propriété) que je prévois d'utiliser.

Soit dit en passant, le test ci-dessus est un bon test pour les nœuds DOM sur tous les navigateurs. Mais si vous voulez être prudent, vérifiez toujours la présence de méthodes et de propriétés et vérifiez leurs types.

EDIT: IE utilise des objets ActiveX pour représenter les nœuds, de sorte que leurs propriétés ne se comportent pas comme de véritables objets JavaScript, par exemple:

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

alors qu'il devrait retourner respectivement "fonction" et true. La seule façon de tester les méthodes est de voir si elles sont définies.

Eugene Lazutkin
la source
"typeof document.body.cloneNode" retourne "object" dans mon IE
Dennis C
Cela ressemble à une réponse décente. Voir ma réponse ci-dessous cependant, stackoverflow.com/a/36894871/1204556
Monarch Wadia
8

Vous pouvez essayer de l'ajouter à un véritable noeud DOM ...

function isDom(obj)
{
    var elm = document.createElement('div');
    try
    {
        elm.appendChild(obj);
    }
    catch (e)
    {
        return false;
    }

    return true;
}
Greg
la source
11
Est-ce que ça marche? C'est toujours une solution. Un créatif à cela.
Justin Meyer
3
+1 pour la créativité et la certitude que cela offre. Cependant, si le nœud fait déjà partie du DOM, vous venez de le supprimer! Donc ... cette réponse est incomplète sans faire le travail pour rajouter l'élément au DOM si nécessaire.
svidgen
4
Je lis ceci après presque 5 ans, et je pense que c'est l'un des plus cool. Il a juste besoin d'être affiné. Vous pouvez essayer d'ajouter un clone du nœud à un élément détaché, par exemple. Si ce n'est pas un objet DOM. quelque chose ira sûrement mal. Pourtant, c'est une solution assez coûteuse.
MaxArt
Ou au lieu d'essayer d'ajouter le clone de l'élément, juste essayer de cloner devrait être suffisant: obj.cloneNode(false). ET n'a aucun effet secondaire.
mauroc8
1
C'est vraiment cher et inutilement compliqué. Voir ma réponse ci-dessous, stackoverflow.com/a/36894871/1204556
Monarch Wadia
7

Pas besoin de hacks, vous pouvez simplement demander si un élément est une instance de l' élément DOM :

const isDOM = el => el instanceof Element
Damjan Pavlica
la source
1
Brillant! Travaux!
Pedro Ferreira
6

Qu'en est-il de Lo-Dash_.isElement ?

$ npm install lodash.iselement

Et dans le code:

var isElement = require("lodash.iselement");
isElement(document.body);
mightyiam
la source
1
J'aime cette solution. C'est simple, et cela fonctionne dans Edge et IE, même pour les éléments dans des iframes séparés, contrairement à la plupart des solutions les plus votées ici.
Elias Zamaria
Cette réponse est utile, bien que l'on aurait besoin de Webpack pour exécuter des modules NPM dans le navigateur.
Edwin Pratt
5

C'est de la belle bibliothèque JavaScript MooTools :

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}
finpingvin
la source
12
Ce code n'affirme pas que l'objet est un élément DOM; seulement qu'il ressemble un peu à un. Tout objet peut recevoir une propriété nodeName et nodeType et satisfaire ce code.
thomasrutter
Cette réponse ne détecte pas tous les types d'éléments HTML. Par exemple, les éléments SVG ne sont pas pris en charge. Voir ma réponse ci-dessous.
Monarch Wadia
Ne fonctionne pas vraiment sur tous les éléments, par exemple SVG. Voir ma réponse ci-dessous, stackoverflow.com/a/36894871/1204556
Monarch Wadia
4

En utilisant la détection de racine trouvée ici , nous pouvons déterminer si, par exemple, alert est un membre de la racine de l'objet, qui est alors susceptible d'être une fenêtre:

function isInAnyDOM(o) { 
  return (o !== null) && !!(o.ownerDocument && (o.ownerDocument.defaultView || o.ownerDocument.parentWindow).alert); // true|false
}

Pour déterminer si l'objet est la fenêtre actuelle est encore plus simple:

function isInCurrentDOM(o) { 
  return (o !== null) && !!o.ownerDocument && (window === (o.ownerDocument.defaultView || o.ownerDocument.parentWindow)); // true|false
}

Cela semble être moins cher que la solution try / catch dans le thread d'ouverture.

Don P

Don P
la source
J'ai testé cela dans les derniers Chrome et FF, ainsi que dans IE11, et cela fonctionne partout, également pour les nœuds de texte et les objets créés via document.createElement()mais non insérés dans DOM aussi. Incroyable (: Merci
Geradlus_RU
Cela ressemble à une réponse décente, bien que la mienne fasse beaucoup de la même chose et soit moins compliquée. stackoverflow.com/a/36894871/1204556
Monarch Wadia
4

ancien thread, mais voici une possibilité mise à jour pour les utilisateurs ie8 et ff3.5 :

function isHTMLElement(o) {
    return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
Zéro
la source
4

Je suggère un moyen simple de tester si une variable est un élément DOM

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

ou comme HTMLGuy l'a suggéré:

const isDomEntity = entity => {
  return typeof entity   === 'object' && entity.nodeType !== undefined
}
romain
la source
1
Beaucoup trop verbeux. La comparaison renverra déjà un booléen:return typeof entity === 'object' && typeof entity.nodeType !== undefined;
HTMLGuy
1
Très intéressant! Parfois, selon les types que vous avez sur vos objects et / ou propriétés, cela peut être très pratique! Tx, @Roman
Pedro Ferreira
3
var IsPlainObject = function ( obj ) { return obj instanceof Object && ! ( obj instanceof Function || obj.toString( ) !== '[object Object]' || obj.constructor.name !== 'Object' ); },
    IsDOMObject = function ( obj ) { return obj instanceof EventTarget; },
    IsDOMElement = function ( obj ) { return obj instanceof Node; },
    IsListObject = function ( obj ) { return obj instanceof Array || obj instanceof NodeList; },

// En fait, je suis plus susceptible de les utiliser en ligne, mais parfois il est bon d'avoir ces raccourcis pour le code de configuration

Erich Horn
la source
obj.constructor.name ne fonctionne pas dans IE, car dans IE, les fonctions n'ont pas la propriété name. Remplacez par obj.constructor! = Object.
mathheadinclouds
3

Cela pourrait être utile: isDOM

//-----------------------------------
// Determines if the @obj parameter is a DOM element
function isDOM (obj) {
    // DOM, Level2
    if ("HTMLElement" in window) {
        return (obj && obj instanceof HTMLElement);
    }
    // Older browsers
    return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);
}

Dans le code ci-dessus, nous utilisons l' opérateur de double négation pour obtenir la valeur booléenne de l'objet passé en argument, de cette façon nous nous assurons que chaque expression évaluée dans l'instruction conditionnelle soit booléenne, en profitant de l' évaluation de court-circuit , donc la fonction retourne trueoufalse

jherax
la source
Tout faux devrait court-circuiter votre booléen. undefined && window.spam("should bork")n'évalue jamais la fausse spamfonction, par exemple. Donc pas !!nécessaire, je ne crois pas. Cela, pouvez-vous fournir un cas de pointe [non académique] où son utilisation est importante?
ruffin du
Merci pour votre aclaration. J'ai utilisé * !! * la double négation pour convertir toutes les expressions en valeur booléenne, pas véridique ou fausse.
jherax
D'accord, mais il n'y a aucune raison pratique de le faire, je ne pense pas - voir ici . Et il n'est certainement pas nécessaire de profiter de l'évaluation de raccourci ici. Même si vous n'avez pas acheté l' !!argument " n'est jamais nécessaire" ( et si vous ne l'avez pas, je suis curieux de savoir pourquoi ), vous pouvez modifier cette ligne return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);et la faire fonctionner de la même manière.
ruffin du
C'est ce que j'ai fait;) plus propre et même effet. Merci.
jherax
2

Vous pouvez voir si l'objet ou le nœud en question renvoie un type de chaîne.

typeof (array).innerHTML === "string" => false
typeof (object).innerHTML === "string" => false
typeof (number).innerHTML === "string" => false
typeof (text).innerHTML === "string" => false

//any DOM element will test as true
typeof (HTML object).innerHTML === "string" => true
typeof (document.createElement('anything')).innerHTML === "string" => true
timewaster51
la source
3
typeof ({innerHTML: ""}).innerHTML === "string"
Qtax
CHAUD! Cette réponse devrait être le gagnant du jeu. if (typeof obj.innerHTML! == 'string') // pas un élément dom.
user3751385
1
J'ai d'abord réagi contre la critique de @Qtax et de thomasrutter sur une réponse antérieure , mais je commence à l'acheter. Bien que je n'aie pas rencontré de chiens charlatans comme des canards exactement comme ça auparavant, je peux voir quelqu'un ne vérifiant pas si quelque chose est un nœud, en cours d'exécution notANode.innerHTML = "<b>Whoops</b>";, puis plus tard, ce code passe son obj contaminé à ce code. Code défensif === meilleur code, toutes choses égales par ailleurs, et ce n'est finalement pas défensif.
ruffin
2

Je pense que le prototypage n'est pas une très bonne solution, mais c'est peut-être la plus rapide: définir ce bloc de code;

Element.prototype.isDomElement = true;
HTMLElement.prototype.isDomElement = true;

que de vérifier la propriété isDomElement de vos objets:

if(a.isDomElement){}

J'espère que ça aide.

Doğuş Atasoy
la source
1
1) changer d'objets que vous ne possédez pas n'est pas conseillé. 2) cela ne détecte pas les éléments qui ne font pas partie du même document.
fregante
2

Selon mdn

Elementest la classe de base la plus générale dont tous les objets d'un Documenthéritage. Il n'a que des méthodes et des propriétés communes à toutes sortes d'éléments.

Nous pouvons l'implémenter isElementpar prototype. Voici mon conseil:

/**
 * @description detect if obj is an element
 * @param {*} obj
 * @returns {Boolean}
 * @example
 * see below
 */
function isElement(obj) {
  if (typeof obj !== 'object') {
    return false
  }
  let prototypeStr, prototype
  do {
    prototype = Object.getPrototypeOf(obj)
    // to work in iframe
    prototypeStr = Object.prototype.toString.call(prototype)
    // '[object Document]' is used to detect document
    if (
      prototypeStr === '[object Element]' ||
      prototypeStr === '[object Document]'
    ) {
      return true
    }
    obj = prototype
    // null is the terminal of object
  } while (prototype !== null)
  return false
}
console.log(isElement(document)) // true
console.log(isElement(document.documentElement)) // true
console.log(isElement(document.body)) // true
console.log(isElement(document.getElementsByTagName('svg')[0])) // true or false, decided by whether there is svg element
console.log(isElement(document.getElementsByTagName('svg'))) // false
console.log(isElement(document.createDocumentFragment())) // false

xianshenglu
la source
1

Je pense que ce que vous devez faire est de vérifier minutieusement certaines propriétés qui seront toujours dans un élément dom, mais leur combinaison ne sera probablement pas dans un autre objet, comme ceci:

var isDom = function (inp) {
    return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};
Andreas Grech
la source
1

Dans Firefox, vous pouvez utiliser le instanceof Node. Cela Nodeest défini dans DOM1 .

Mais ce n'est pas si simple dans IE.

  1. "instanceof ActiveXObject" peut seulement dire qu'il s'agit d'un objet natif.
  2. "typeof document.body.appendChild == 'object'" indique qu'il peut s'agir d'un objet DOM, mais que quelque chose d'autre peut avoir la même fonction.

Vous ne pouvez vous assurer qu'il s'agit bien d'un élément DOM qu'en utilisant la fonction DOM et intercepter s'il y a une exception. Cependant, cela peut avoir un effet secondaire (par exemple, changer l'état interne de l'objet / les performances / la fuite de mémoire)

Dennis C
la source
1

C'est peut-être une alternative? Testé dans Opera 11, FireFox 6, Internet Explorer 8, Safari 5 et Google Chrome 16.

function isDOMNode(v) {
  if ( v===null ) return false;
  if ( typeof v!=='object' ) return false;
  if ( !('nodeName' in v) ) return false; 

  var nn = v.nodeName;
  try {
    // DOM node property nodeName is readonly.
    // Most browsers throws an error...
    v.nodeName = 'is readonly?';
  } catch (e) {
    // ... indicating v is a DOM node ...
    return true;
  }
  // ...but others silently ignore the attempt to set the nodeName.
  if ( v.nodeName===nn ) return true;
  // Property nodeName set (and reset) - v is not a DOM node.
  v.nodeName = nn;

  return false;
}

La fonction ne sera pas dupée par exemple par ceci

isDOMNode( {'nodeName':'fake'} ); // returns false
Snoozer Man
la source
2
Bon essai, mais la gestion des exceptions coûte trop cher si elle peut être évitée. De plus, ES5 vous permet de définir des propriétés en lecture seule pour les objets.
Andy E
1

Voici ce que j'ai compris:

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";
        }
    }
})();

Pour améliorer les performances, j'ai créé une fonction auto-invoquante qui teste les capacités du navigateur une seule fois et attribue la fonction appropriée en conséquence.

Le premier test devrait fonctionner dans la plupart des navigateurs modernes et a déjà été discuté ici. Il teste simplement si l'élément est une instance de HTMLElement. Très simple.

Le second est le plus intéressant. Voici sa fonctionnalité principale:

return el instanceof (document.createElement(el.nodeName)).constructor

Il teste si el est une instance du constructeur qu'il prétend être. Pour ce faire, nous devons avoir accès au constructeur d'un élément. C'est pourquoi nous testons cela dans la déclaration if. IE7 par exemple échoue, car (document.createElement("a")).constructorest undefineddans IE7.

Le problème avec cette approche est que ce document.createElementn'est vraiment pas la fonction la plus rapide et pourrait facilement ralentir votre application si vous testez beaucoup d'éléments avec elle. Pour résoudre ce problème, j'ai décidé de mettre en cache les constructeurs. L'objet ElementConstructorsa nodeNames comme clés avec ses constructeurs correspondants comme valeurs. Si un constructeur est déjà mis en cache, il l'utilise à partir du cache, sinon il crée l'élément, met en cache son constructeur pour un accès futur, puis le teste.

Le troisième test est le repli désagréable. Il teste si el est an object, a une nodeTypepropriété définie sur 1et une chaîne as nodeName. Bien sûr, ce n'est pas très fiable, mais la grande majorité des utilisateurs ne devraient même pas se replier jusqu'à présent.

C'est l'approche la plus fiable que j'ai trouvée tout en maintenant des performances aussi élevées que possible.

Oliver Sartun
la source
1

Testez si objhérite de Node .

if (obj instanceof Node){
    // obj is a DOM Object
}

Node est une interface de base dont HTMLElement et Text héritent.

soslan
la source
1

différencier un objet js brut d'un HTMLElement

function isDOM (x){
     return /HTML/.test( {}.toString.call(x) );
 }

utilisation:

isDOM( {a:1} ) // false
isDOM( document.body ) // true

// OU

Object.defineProperty(Object.prototype, "is",
    {
        value: function (x) {
            return {}.toString.call(this).indexOf(x) >= 0;
        }
    });

utilisation:

o={}; o.is("HTML") // false o=document.body; o.is("HTML") // true

bortunac
la source
0

voici une astuce en utilisant jQuery

var obj = {};
var element = document.getElementById('myId'); // or simply $("#myId")

$(obj).html() == undefined // true
$(element).html() == undefined // false

donc le mettre dans une fonction:

function isElement(obj){

   return (typeOf obj === 'object' && !($(obj).html() == undefined));

}
Matus
la source
2
jQuery le fait en interne, elem.nodeType === 1alors pourquoi ne pas enregistrer la surcharge d'appel et la dépendance jQuery et demander à votre fonction isElement de le faire elle-même?
Joseph Lennox
C'est 2016, dites simplement "non".
Thomas McCabe
0

Ne pas marteler cela ou quoi que ce soit, mais pour les navigateurs compatibles ES5, pourquoi pas seulement:

function isDOM(e) {
  return (/HTML(?:.*)Element/).test(Object.prototype.toString.call(e).slice(8, -1));
}

Ne fonctionnera pas sur et pas sûr de nœuds texte au sujet de l' ombre DOM ou DocumentFragments etc. , mais va travailler sur presque tous les éléments de balise HTML.

Travis Kaufman
la source
0

Cela fonctionnera pour presque tous les navigateurs. (Pas de distinction entre les éléments et les nœuds ici)

function dom_element_check(element){
    if (typeof element.nodeType !== 'undefined'){
        return true;
    }
    return false;
}
Zv_oDD
la source
tout d'abord, vous n'avez pas besoin de retourner true ou return false, renvoyez simplement l'instruction if. Deuxièmement, cela retournera vrai pour {nodeType: 1}
bluejayke
0

Une méthode à droite absolue, check target est un vrai code primaire d'élément html:

    (function (scope) {
        if (!scope.window) {//May not run in window scope
            return;
        }
        var HTMLElement = window.HTMLElement || window.Element|| function() {};

        var tempDiv = document.createElement("div");
        var isChildOf = function(target, parent) {

            if (!target) {
                return false;
            }
            if (parent == null) {
                parent = document.body;
            }
            if (target === parent) {
                return true;
            }
            var newParent = target.parentNode || target.parentElement;
            if (!newParent) {
                return false;
            }
            return isChildOf(newParent, parent);
        }
        /**
         * The dom helper
         */
        var Dom = {
            /**
             * Detect if target element is child element of parent
             * @param {} target The target html node
             * @param {} parent The the parent to check
             * @returns {} 
             */
            IsChildOf: function (target, parent) {
                return isChildOf(target, parent);
            },
            /**
             * Detect target is html element
             * @param {} target The target to check
             * @returns {} True if target is html node
             */
            IsHtmlElement: function (target) {
                if (!X.Dom.IsHtmlNode(target)) {
                    return false;
                }
                return target.nodeType === 1;
            },
            /**
             * Detect target is html node
             * @param {} target The target to check
             * @returns {} True if target is html node
             */
            IsHtmlNode:function(target) {
                if (target instanceof HTMLElement) {
                    return true;
                }
                if (target != null) {
                    if (isChildOf(target, document.documentElement)) {
                        return true;
                    }
                    try {
                        tempDiv.appendChild(target.cloneNode(false));
                        if (tempDiv.childNodes.length > 0) {
                            tempDiv.innerHTML = "";
                            return true;
                        }
                    } catch (e) {

                    }
                }
                return false;
            }
        };
        X.Dom = Dom;
    })(this);

Test dans IE 5

dexiang
la source
0

Chaque DOMElement.constructor renvoie la fonction HTML ... Element () ou [Object HTML ... Element] donc ...

function isDOM(getElem){
    if(getElem===null||typeof getElem==="undefined") return false;
    var c = getElem.constructor.toString();
    var html = c.search("HTML")!==-1;
    var element = c.search("Element")!==-1;
    return html&&element;
}
Paweł
la source
0

J'ai une façon spéciale de le faire qui n'a pas encore été mentionnée dans les réponses.

Ma solution est basée sur quatre tests. Si l'objet passe tous les quatre, alors c'est un élément:

  1. L'objet n'est pas nul.

  2. L'objet a une méthode appelée "appendChild".

  3. La méthode "appendChild" a été héritée de la classe Node , et n'est pas seulement une méthode imposteur (une propriété créée par l'utilisateur avec un nom identique).

  4. L'objet est de type noeud 1 (élément). Objets qui héritent des méthodes du classe Node sont toujours des Nodes, mais pas nécessairement des Elements.

Q: Comment puis-je vérifier si une propriété donnée est héritée et n'est pas seulement un imposteur?

R: Un test simple pour voir si une méthode a vraiment été héritée de Node consiste à vérifier d'abord que la propriété a un type "d'objet" ou de "fonction". Ensuite, convertissez la propriété en chaîne et vérifiez si le résultat contient le texte "[Code natif]". Si le résultat ressemble à ceci:

function appendChild(){
[Native Code]
}

Ensuite, la méthode a été héritée de l'objet Node. Voir https://davidwalsh.name/detect-native-function

Et enfin, réunissant tous les tests, la solution est:

function ObjectIsElement(obj) {
    var IsElem = true;
    if (obj == null) {
        IsElem = false;
    } else if (typeof(obj.appendChild) != "object" && typeof(obj.appendChild) != "function") {
        //IE8 and below returns "object" when getting the type of a function, IE9+ returns "function"
        IsElem = false;
    } else if ((obj.appendChild + '').replace(/[\r\n\t\b\f\v\xC2\xA0\x00-\x1F\x7F-\x9F ]/ig, '').search(/\{\[NativeCode]}$/i) == -1) {
        IsElem = false;
    } else if (obj.nodeType != 1) {
        IsElem = false;
    }
    return IsElem;
}
user3163495
la source
0
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element

Cela vérifiera même s'il s'agit d'un élément DOM jQuery ou JavaScript

Arjun Kakkar
la source
0

La seule façon de garantir que vous vérifiez un HTMLEement réel, et pas seulement un objet avec les mêmes propriétés qu'un élément HTML, est de déterminer s'il hérite de Node, car il est impossible de créer un nouveau Node () en JavaScript. (sauf si la fonction Node native est écrasée, mais vous n'avez pas de chance). Alors:

function isHTML(obj) {
    return obj instanceof Node;
}

console.log(
  isHTML(test),
  isHTML(ok),
  isHTML(p),
  isHTML(o),
  isHTML({
    constructor: {
      name: "HTML"
    }
  }),
  isHTML({
    __proto__: {
      __proto__: {
        __proto__: {
          __proto__: {
            constructor: {
              constructor: { 
                name: "Function"
                
              },
              name: "Node"
            }
          }
        }
      }
    }
  }),
)
<div id=test></div>
<blockquote id="ok"></blockquote>
<p id=p></p>
<br id=o>
<!--think of anything else you want--!>

bluejayke
la source