Wie überprüfen Sie, ob ein JavaScript-Objekt ein DOM-Objekt ist?

247

Ich versuche zu bekommen:

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

In meinen eigenen Skripten habe ich dies nur verwendet, da ich es nie tagNameals Eigenschaft brauchte :

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

Für das zweite Objekt habe ich mir als schnelle Lösung Folgendes ausgedacht - was meistens funktioniert. ;)

Das Problem ist, dass es von Browsern abhängt, die schreibgeschützte Eigenschaften erzwingen, was nicht alle tun.

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

Gibt es einen guten Ersatz?

Jonathan Lonowski
quelle
3
Bin ich stumpf in der Frage, ob ein "DOM-Objekt" nicht nur Elemente, sondern auch alle Knoten (Textknoten, Attribute usw.) abdecken sollte? Alle Antworten und die Art und Weise, wie Sie die Frage gestellt haben, deuten darauf hin, dass es sich bei dieser Frage speziell um Elemente handelt ...
Mike Nagetier

Antworten:

300

Dies könnte von Interesse sein:

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 ist Teil des DOM, Level2 .

Update 2 : So habe ich es in meiner eigenen Bibliothek implementiert: (Der vorherige Code hat in Chrome nicht funktioniert, da Node und HTMLElement Funktionen anstelle des erwarteten Objekts sind. Dieser Code wird in FF3, IE7, Chrome 1 und Opera getestet 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"
);
}
etwas
quelle
11
Es ist erwähnenswert, dass dies bei Elementen, die zu anderen Fenstern / Rahmen gehören, nicht funktioniert. Ententippen ist der empfohlene Ansatz
Andy E
2
Sie können es täuschen mit:function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
Kernel James
11
WTF Tatsache: Firefox 5 und frühere Rückkehr truefür [] instanceof HTMLElement.
Rob W
6
Übrigens HTMLElementist immer ein function, typeofwirft Sie also von der Strecke und führt den zweiten Teil der Anweisung aus. Sie können es versuchen, wenn Sie möchten instanceof Object, da die Funktion eine Instanz von ist Object, oder einfach explizit prüfen typeof === "function", weil Nodeund HTMLElementbeide native Objektfunktionen sind.
Roland
2
Wenn Sie anrufen isElement(0), wird 0 zurückgegeben, nicht false ... Warum ist das so und wie kann ich das verhindern?
Jessica
68

Der folgende IE8-kompatible, supereinfache Code funktioniert einwandfrei.

Die akzeptierte Antwort erkennt nicht alle Arten von HTML-Elementen. Beispielsweise werden SVG-Elemente nicht unterstützt. Im Gegensatz dazu funktioniert diese Antwort sowohl für HTML als auch für SVG.

Sehen Sie es hier in Aktion: https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}
Monarch Wadia
quelle
3
'Element' ist auf IE7
Dan
49
Ich bin der Meinung, dass jeder, der noch IE7 verwendet, die fünf Sekunden damit verbringen sollte, einen besseren Browser herunterzuladen, anstatt ihn uns zu überlassen, Tage oder Wochen zu investieren, um seine Weigerung zu umgehen, mit der Zeit zu gehen.
Mopsyd
1
Ich stimme @mopsyd zu, aber der Autor der Antwort gibt an, dass es in IE7 funktioniert, das aus Gründen der Korrektheit möglicherweise aktualisiert werden muss.
Lajos Meszaros
1
Aktualisiert, um IE9 zu sagen. Ich bin mir nicht sicher, ob IE8 dies unterstützt.
Monarch Wadia
1
@ MonarchWadia Ja, es wird in IE8 unterstützt. Beachten Sie jedoch, dass dies für documentelement nicht true zurückgibt (in allen Browsern). Wenn Sie es brauchen, sollten Sie versuchen:x instanceof Element || x instanceof HTMLDocument
S.Serpooshan
11

Alle Lösungen oben und unten (einschließlich meiner Lösung) können falsch sein, insbesondere im IE. Es ist durchaus möglich, einige Objekte / Methoden / Eigenschaften (neu) zu definieren, um einen DOM-Knoten nachzuahmen, der den Test ungültig macht.

Normalerweise verwende ich den Test im Enten-Schreibstil: Ich teste speziell auf Dinge, die ich benutze. Wenn ich beispielsweise einen Knoten klonen möchte, teste ich ihn folgendermaßen:

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

Grundsätzlich ist es eine kleine Überprüfung der geistigen Gesundheit + der direkte Test für eine Methode (oder eine Eigenschaft), die ich verwenden möchte.

Der obige Test ist übrigens ein guter Test für DOM-Knoten in allen Browsern. Wenn Sie jedoch auf der sicheren Seite sein möchten, überprüfen Sie immer das Vorhandensein von Methoden und Eigenschaften und deren Typen.

BEARBEITEN: Der IE verwendet ActiveX-Objekte zur Darstellung von Knoten, sodass sich ihre Eigenschaften nicht als echtes JavaScript-Objekt verhalten. Beispiel:

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

während es "Funktion" truebzw. zurückgeben sollte. Die einzige Möglichkeit, Methoden zu testen, besteht darin, festzustellen, ob sie definiert sind.

Eugene Lazutkin
quelle
"typeof document.body.cloneNode" gibt "object" in meinem IE zurück
Dennis C
Das sieht nach einer anständigen Antwort aus. Siehe meine Antwort unten, stackoverflow.com/a/36894871/1204556
Monarch Wadia
8

Sie können versuchen, es an einen echten DOM-Knoten anzuhängen ...

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

    return true;
}
Greg
quelle
11
Funktioniert das? Es ist immer noch eine Lösung. Ein kreativer dazu.
Justin Meyer
3
+1 für die Kreativität und Sicherheit, die dies bietet. Wenn der Knoten jedoch bereits Teil des DOM ist, haben Sie ihn gerade entfernt! Also ... diese Antwort ist unvollständig, ohne die Arbeit zu erledigen, um das Element bei Bedarf erneut zum DOM hinzuzufügen.
Svidgen
4
Ich lese das nach fast 5 Jahren und ich denke, es ist eines der coolsten. Es muss nur verfeinert werden. Sie können beispielsweise versuchen, einen Klon des Knotens an ein getrenntes Element anzuhängen . Wenn das kein DOM-Objekt ist. etwas wird sicherlich schief gehen. Trotzdem eine ziemlich teure Lösung.
MaxArt
Oder anstatt zu versuchen, den Klon des Elements anzuhängen , sollte es ausreichen , nur zu klonen : obj.cloneNode(false). UND hat keine Nebenwirkungen.
Mauroc8
1
Das ist sehr teuer und unnötig kompliziert. Siehe meine Antwort unten, stackoverflow.com/a/36894871/1204556
Monarch Wadia
7

Sie benötigen keine Hacks. Sie können einfach fragen, ob ein Element eine Instanz des DOM- Elements ist :

const isDOM = el => el instanceof Element
Damjan Pavlica
quelle
1
Brillant! Funktioniert!
Pedro Ferreira
6

Wie wäre es mit Lo-Dash_.isElement ?

$ npm install lodash.iselement

Und im Code:

var isElement = require("lodash.iselement");
isElement(document.body);
mächtig
quelle
1
Ich mag diese Lösung. Es ist einfach und funktioniert in Edge und IE, auch für Elemente in separaten Iframes, im Gegensatz zu den meisten Lösungen mit der höchsten Bewertung.
Elias Zamaria
Diese Antwort ist hilfreich, obwohl man Webpack benötigt, um NPM-Module im Browser auszuführen.
Edwin Pratt
5

Dies ist aus der schönen JavaScript-Bibliothek MooTools :

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}
Finpingvin
quelle
12
Dieser Code behauptet nicht, dass das Objekt ein DOM-Element ist. nur dass es ein bisschen wie eins aussieht. Jedes Objekt kann mit den Eigenschaften nodeName und nodeType versehen werden und diesen Code erfüllen.
Thomasrutter
Diese Antwort erkennt nicht alle Arten von HTML-Elementen. Beispielsweise werden SVG-Elemente nicht unterstützt. Siehe meine Antwort unten.
Monarch Wadia
Funktioniert nicht wirklich bei allen Elementen, zum Beispiel SVG. Siehe meine Antwort unten, stackoverflow.com/a/36894871/1204556
Monarch Wadia
4

Mithilfe der hier gefundenen Stammerkennung können wir feststellen, ob z. B. alert ein Mitglied des Stamms des Objekts ist, der dann wahrscheinlich ein Fenster ist:

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

Um festzustellen, ob das Objekt das aktuelle Fenster ist, ist es noch einfacher:

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

Dies scheint günstiger zu sein als die Try / Catch-Lösung im Eröffnungsfaden.

Don P.

Don P.
quelle
Ich habe dies in den neuesten Versionen von Chrome und FF sowie in IE11 getestet und es funktioniert überall, auch für Textknoten und Objekte, die über document.createElement()DOM erstellt, aber nicht in DOM eingefügt wurden. Erstaunlich (: Danke
Geradlus_RU
Das sieht nach einer anständigen Antwort aus, obwohl meine viele der gleichen Dinge macht und weniger kompliziert ist. stackoverflow.com/a/36894871/1204556
Monarch Wadia
4

alter Thread, aber hier ist eine aktualisierte Möglichkeit für Benutzer von ie8 und ff3.5 :

function isHTMLElement(o) {
    return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
Chiffre
quelle
4

Ich schlage einen einfachen Weg vor, um zu testen, ob eine Variable ein DOM-Element ist

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

oder wie von HTMLGuy vorgeschlagen:

const isDomEntity = entity => {
  return typeof entity   === 'object' && entity.nodeType !== undefined
}
römisch
quelle
1
Viel zu ausführlich. Der Vergleich wird bereits einen Booleschen return typeof entity === 'object' && typeof entity.nodeType !== undefined;
Wert zurückgeben
1
Sehr interessant! Abhängig von den Typen, die Sie auf Ihren objects und / oder Poperties haben, kann dies manchmal sehr praktisch sein! 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; },

// Tatsächlich verwende ich diese Inline eher nicht, aber manchmal ist es gut, diese Verknüpfungen für den Setup-Code zu haben

Erich Horn
quelle
obj.constructor.name funktioniert im IE nicht, da Funktionen im IE nicht über die Eigenschaft name verfügen. Ersetzen durch obj.constructor! = Objekt.
Mathheadinclouds
3

Dies könnte hilfreich sein: 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);
}

Im obigen Code verwenden wir den Doppel-Negationsoperator , um den booleschen Wert des als Argument übergebenen Objekts abzurufen. Auf diese Weise stellen wir sicher, dass jeder in der bedingten Anweisung ausgewertete Ausdruck boolesch ist, wobei wir die Kurzschlussauswertung und damit die Funktion nutzen gibt trueoder zurückfalse

Jherax
quelle
Alles, was falsch ist, sollte Ihren Booleschen Wert kurzschließen. undefined && window.spam("should bork")bewertet spamzum Beispiel niemals die gefälschte Funktion. Also nicht !!nötig, glaube ich nicht. Können Sie einen [nicht-akademischen] Randfall liefern, bei dem es auf seine Verwendung ankommt?
Ruffin
Vielen Dank für Ihre Erklärung. Ich habe * !! * doppelte Negation verwendet , um alle Ausdrücke in boolesche Werte umzuwandeln, nicht wahr oder falsch.
Jherax
Richtig, aber es gibt keinen praktischen Grund dafür, glaube ich nicht - siehe hier . Und es ist sicherlich nicht notwendig, hier die Short-Cut-Bewertung zu nutzen. Selbst wenn Sie das !!Argument " wird nie benötigt" nicht gekauft haben ( und wenn Sie es nicht tun, bin ich neugierig, warum nicht ), können Sie diese Zeile bearbeiten return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);und sie genauso funktionieren lassen.
Ruffin
Das habe ich getan;) sauberer und gleicher Effekt. Danke.
Jherax
2

Sie können sehen, ob das betreffende Objekt oder der betreffende Knoten einen Zeichenfolgentyp zurückgibt.

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
quelle
3
typeof ({innerHTML: ""}).innerHTML === "string"
Qtax
HEISS! Diese Antwort sollte der Gewinner des Spiels sein. if (typeof obj.innerHTML! == 'string') // kein dom-Element.
user3751385
1
Ich habe anfangs gegen die Kritik von @Qtax und thomasrutter auf eine frühere Antwort reagiert , aber ich fange an, sie zu kaufen. Obwohl ich noch nie zuvor auf Hunde gestoßen bin, die genau wie diese wie Enten quaken, kann ich jemanden sehen, der nicht prüft, ob etwas ein Knoten ist, läuft notANode.innerHTML = "<b>Whoops</b>";und später diesen Code sein kontaminiertes Objekt an diesen Code weitergeben lässt. Defensiver Code === besserer Code, alle anderen Dinge sind gleich, und dies ist letztendlich nicht defensiv.
Ruffin
2

Für diejenigen, die Angular verwenden:

angular.isElement

https://docs.angularjs.org/api/ng/function/angular.isElement

Alvis
quelle
Nützlicher, um Angulars Code einzuschließen : function isElement(node) { return !!(node && (node.nodeName || (node.prop && node.attr && node.find))); }Sieht ein bisschen aus wie @ finpingvins . Beachten Sie, dass es bestimmt, " ob eine Referenz ein DOM-Element (oder ein umschlossenes jQuery-Element) ist. "
Ruffin
2

Ich denke, Prototyping ist keine sehr gute Lösung, aber vielleicht ist dies die schnellste: Definieren Sie diesen Codeblock;

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

als überprüfen Sie Ihre Objekte isDomElement-Eigenschaft:

if(a.isDomElement){}

Ich hoffe das hilft.

Doğuş Atasoy
quelle
1
1) Das Ändern von Objekten, die Sie nicht besitzen, ist nicht ratsam. 2) Dadurch werden keine Elemente erkannt, die nicht Teil desselben Dokuments sind.
Fregante
2

Laut mdn

Elementist die allgemeinste Basisklasse, von der alle Objekte in einem Documenterben. Es hat nur Methoden und Eigenschaften, die allen Arten von Elementen gemeinsam sind.

Wir können isElementnach Prototyp implementieren . Hier ist mein Rat:

/**
 * @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
quelle
1

Ich denke, Sie müssen einige Eigenschaften, die sich immer in einem dom-Element befinden, gründlich überprüfen, aber ihre Kombination wird sich höchstwahrscheinlich nicht in einem anderen Objekt befinden, wie z.

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

In Firefox können Sie die verwenden instanceof Node. Das Nodeist in DOM1 definiert .

Aber das ist im IE nicht so einfach.

  1. "instanceof ActiveXObject" kann nur erkennen, dass es sich um ein natives Objekt handelt.
  2. "typeof document.body.appendChild == 'object'" sagt, dass es sich möglicherweise um ein DOM-Objekt handelt, aber auch um etwas anderes, das dieselbe Funktion hat.

Sie können nur mithilfe der DOM-Funktion sicherstellen, dass es sich um ein DOM-Element handelt, und bei Ausnahmen abfangen. Es kann jedoch Nebenwirkungen haben (z. B. Ändern des internen Status / der Leistung / des Speicherverlusts des Objekts)

Dennis C.
quelle
1

Vielleicht ist das eine Alternative? Getestet in Opera 11, FireFox 6, Internet Explorer 8, Safari 5 und 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;
}

Die Funktion lässt sich zB nicht täuschen

isDOMNode( {'nodeName':'fake'} ); // returns false
Snoozer Man
quelle
2
Guter Versuch, aber die Behandlung von Ausnahmen ist zu teuer, wenn sie vermieden werden kann. Außerdem können Sie mit ES5 schreibgeschützte Eigenschaften für Objekte definieren.
Andy E
1

Folgendes habe ich herausgefunden:

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

Um die Leistung zu verbessern, habe ich eine selbstaufrufende Funktion erstellt, die die Funktionen des Browsers nur einmal testet und die entsprechende Funktion entsprechend zuweist.

Der erste Test sollte in den meisten modernen Browsern funktionieren und wurde hier bereits besprochen. Es wird nur getestet, ob das Element eine Instanz von ist HTMLElement. Sehr einfach.

Der zweite ist der interessanteste. Dies ist seine Kernfunktionalität:

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

Es wird geprüft, ob el eine Instanz des Konstrukts ist, das es vorgibt zu sein. Dazu benötigen wir Zugriff auf den Konstruktor eines Elements. Deshalb testen wir dies in der if-Anweisung. IE7 zum Beispiel schlägt fehl, weil (document.createElement("a")).constructores undefinedin IE7 ist.

Das Problem bei diesem Ansatz ist, dass dies document.createElementnicht die schnellste Funktion ist und Ihre Anwendung leicht verlangsamen kann, wenn Sie viele Elemente damit testen. Um dies zu lösen, habe ich beschlossen, die Konstruktoren zwischenzuspeichern. Das Objekt ElementConstructorshat Knotennamen als Schlüssel mit den entsprechenden Konstruktoren als Werte. Wenn ein Konstruktor bereits zwischengespeichert ist, verwendet er ihn aus dem Cache. Andernfalls erstellt er das Element, speichert seinen Konstruktor für den zukünftigen Zugriff zwischen und testet ihn anschließend.

Der dritte Test ist der unangenehme Fallback. Es wird getestet, ob el ein ist object, eine nodeTypeEigenschaft auf gesetzt ist 1und eine Zeichenfolge als nodeName. Dies ist natürlich nicht sehr zuverlässig, aber die überwiegende Mehrheit der Benutzer sollte noch nicht einmal zurückgreifen.

Dies ist der zuverlässigste Ansatz, den ich mir ausgedacht habe, während die Leistung so hoch wie möglich gehalten wurde.

Oliver Sartun
quelle
1

Testen Sie, ob es objvon Node erbt .

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

Der Knoten ist eine grundlegende Schnittstelle, von der HTMLElement und Text erben.

Soslan
quelle
1

Unterscheiden Sie ein rohes js-Objekt von einem HTMLElement

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

verwenden:

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

// ODER

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

verwenden:

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

Bortunac
quelle
0

Hier ist ein Trick mit jQuery

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

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

also in eine Funktion setzen:

function isElement(obj){

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

}
Matus
quelle
2
jQuery tut elem.nodeType === 1dies intern. Warum nicht den Anrufaufwand und die jQuery-Abhängigkeit speichern und Ihre isElement-Funktion dies selbst tun lassen?
Joseph Lennox
Es ist 2016, sag einfach "nein".
Thomas McCabe
0

Nicht auf dieses oder irgendetwas zu hämmern, sondern auf ES5-kompatible Browser, warum nicht einfach:

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

Wird nicht auf TextNodes arbeiten und nicht sicher Schatten DOM oder DocumentFragments usw. aber werden fast alle HTML - Tag - Elemente arbeiten.

Travis Kaufman
quelle
0

Dies funktioniert für fast jeden Browser. (Keine Unterscheidung zwischen Elementen und Knoten hier)

function dom_element_check(element){
    if (typeof element.nodeType !== 'undefined'){
        return true;
    }
    return false;
}
Zv_oDD
quelle
Zunächst müssen Sie weder true noch false zurückgeben, sondern nur die if-Anweisung zurückgeben. Zweitens wird dies für {nodeType: 1}
bluejayke
0

Als absolut richtige Methode ist check target ein echter HTML-Element-Primärcode:

    (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 in IE 5

Dexiang
quelle
0

Jeder DOMElement.constructor gibt die Funktion HTML ... Element () oder [Object HTML ... Element] zurück, also ...

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ł
quelle
0

Ich habe eine spezielle Möglichkeit, dies zu tun, die in den Antworten noch nicht erwähnt wurde.

Meine Lösung basiert auf vier Tests. Wenn das Objekt alle vier übergibt, ist es ein Element:

  1. Das Objekt ist nicht null.

  2. Das Objekt hat eine Methode namens "appendChild".

  3. Die Methode "appendChild" wurde von der Node- Klasse geerbt und ist nicht nur eine Betrüger-Methode (eine vom Benutzer erstellte Eigenschaft mit identischem Namen).

  4. Das Objekt ist vom Knotentyp 1 (Element). Objekte, die Methoden von der Node- Klasse erben, sind immer Nodes, aber nicht unbedingt Elements.

F: Wie überprüfe ich, ob eine bestimmte Eigenschaft vererbt wurde und nicht nur ein Betrüger ist?

A: Ein einfacher Test, um festzustellen, ob eine Methode wirklich von Node geerbt wurde, besteht darin, zunächst zu überprüfen, ob die Eigenschaft einen Typ von "Objekt" oder "Funktion" hat. Konvertieren Sie anschließend die Eigenschaft in eine Zeichenfolge und prüfen Sie, ob das Ergebnis den Text "[Native Code]" enthält. Wenn das Ergebnis ungefähr so ​​aussieht:

function appendChild(){
[Native Code]
}

Dann wurde die Methode vom Node-Objekt geerbt. Siehe https://davidwalsh.name/detect-native-function

Und schließlich, wenn alle Tests zusammengeführt werden, lautet die Lösung:

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
quelle
0
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element

Dies prüft, ob es sich um ein jQuery- oder JavaScript-DOM-Element handelt

Arjun Kakkar
quelle
0

Die einzige Möglichkeit, um sicherzustellen, dass Sie ein tatsächliches HTMLEement und nicht nur ein Objekt mit denselben Eigenschaften wie ein HTML-Element überprüfen, besteht darin, festzustellen, ob es von Node erbt, da es unmöglich ist, einen neuen Node () in JavaScript zu erstellen. (es sei denn, die native Knotenfunktion wird überschrieben, aber dann haben Sie kein Glück). So:

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
quelle